I'm trying to implement a DropDownButton where the list of items will be displayed from its start.
Meaning, I want the items list to be opened and displayed as if the items list "completes" the DropDownButton - right after the green underline and regardless to the current value (see current behavior below).
I tried looking up online some information of how to achieve it but it yielded nothing. Also, I tried wrapping the DropDownButton with widgets to set the alignment of the drop of items and unfortunately I managed nothing.
What am I missing?
How can I set The DropDownButton's list to be opened so that the items will be aligned from its start?
here is my code:
final List<String> categories = ['', 'Cakes', 'Chocolate', 'Balloons', 'Flowers', 'Greeting Cards','Gift Cards', 'Other'];
String _currCategory = categories[0];
#override
Widget build(BuildContext context){
return Material(
child: Scaffold(
resizeToAvoidBottomInset: true,
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.transparent,
key: _scaffoldKeyMainScreen,
appBar: AppBar(
centerTitle: true,
elevation: 0.0,
backgroundColor: Colors.lightGreen[800],
actions: <Widget>[
///Checkout - cart
IconButton(
icon: Icon(Icons.shopping_cart_outlined),
onPressed: () {}
),
/// WishList
IconButton(
icon: Icon(Icons.favorite),
onPressed: () => {}
],
leading: Icon(Icons.logout),
title: Text('My app'),
),
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width * 0.35,
color: Colors.lightGreen[800],
),
),
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
child: Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Align(
alignment: Alignment.center,
child: Container(
color: Colors.transparent,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(11.0),
child: Center(
child: Text(' Sort by: ',
style: TextStyle(
color: Colors.black,
),
),
),
),
Container(
color: Colors.transparent,
child: Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.transparent,
buttonTheme: ButtonTheme.of(context).copyWith(
alignedDropdown: true,
)
),
child: DropdownButton<String>(
dropdownColor: Colors.white,
underline: Container(
height: 2,
color: Colors.lightGreen[300],
),
icon: Icon(Icons.keyboard_arrow_down_outlined,
color: Colors.lightGreen[200],
),
elevation: 8,
value: _currCategory,
items: categories
.map<DropdownMenuItem<String>>((e) => DropdownMenuItem(
child: Text(e, style: TextStyle(color: Colors.lightGreen[300]),),
value: e,
)
).toList(),
onChanged: (String value) {
setState(() {
_currCategory = value;
});
},
)
),
),
///in my app I have a GridView that is built from items loaded from Firebase
///but I think it has nothing to do with the current problem so I placed a symbolic text
Center(child: Text(_currCategory)),
],
),
),
),
),
],
),
),
),
]
),
)
);
}
current behavior: App Demo of Current Behavior
I was finally able to solve this and found exactly what I was looking for here:
https://stackoverflow.com/a/59859741/13727011
Also, there is an excellent YouTube tutorial on how to implement such Dropdown here:
https://youtu.be/j5DkShqvIAU
Related
So I have a container with 9 ElevatedButtons (code shown below) i would like to change the color of the selected button, but there can only be 1 selected button at a time, how would i go about doing this? So if one button is selected the button will go green, but if another button in the container is clicked it will revert back the color of the previously selected color and change the current selected button to green.
here is the container with the elevated buttons:
Container(
padding: EdgeInsets.all(25),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white),
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("10.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("20.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("50.000"))),
),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("100.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("250.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("500.000"))),
),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("750.000"))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("1.000.000", style: TextStyle(fontSize: 13)))),
),
),
),
SizedBox(width: 10),
Expanded(
child: Material(
elevation: 2,
child: InkWell(
onTap: (){},
child: Container(
padding: EdgeInsets.all(15),
child: Center(child: Text("2.000.000", style: TextStyle(fontSize: 13)))),
),
),
),
],
),
],
),
),
If i have to guess I would think I would need to put it inside of a map, but I'm not sure how to go about doing this. I would prefer to learn the manual implementation but if needed i'm fine with using packages if needed.
For this work You can use ChoiceChip instead of using Material Button directly
A material design choice chip.
ChoiceChips represent a single choice from a set. Choice chips contain
related descriptive text or categories.
class MyThreeOptions extends StatefulWidget {
const MyThreeOptions({Key? key}) : super(key: key);
#override
State<MyThreeOptions> createState() => _MyThreeOptionsState();
}
class _MyThreeOptionsState extends State<MyThreeOptions> {
int? _value = 1;
#override
Widget build(BuildContext context) {
return Wrap(
children: List<Widget>.generate(
3,
(int index) {
return ChoiceChip(
label: Text('Item $index'),
selected: _value == index,
onSelected: (bool selected) {
setState(() {
_value = selected ? index : null;
});
},
);
},
).toList(),
);
}
}
create a new StatefulWidget and just return a button inside that. call the functions and api's in that file only. and call this class name as the child instead ofyour old button. Works for me.
here is my app
as you can see working well, I installed this on my phone, and it works fine too.
and I send this to my friend, and his phone showing like this
mine and his phone is same phone, literally same phone, but in his and any others phone is showing this overflow, mine and this emulator have no problem, how do i fix overflow problem
class Homescreen extends StatelessWidget {
const Homescreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: const Text("Pluto Guess Game"),
backgroundColor: Colors.white60,
),
body: Container(
color: Colors.white,
child: SafeArea(
child: ListView(
children: [
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: mbappe
)
PlayerWidget(
player: ramos
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PlayerWidget(
player: messi
),
PlayerWidget(
player: neymar
)
],
),
),
Card(
child: IconButton(
icon: const Icon(Icons.gesture),
iconSize: 50,
color: Colors.black,
splashColor: Colors.orange,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (nav) {
return const Asking();
},
),
);
},
),
),
],
),
),
),
),
);
}
}
and also I'm new at flutter, I know I'm doing lot of mistake in this code please suggest that also
->Use This Code
Widget build(BuildContext context) {
double h = MediaQuery.of(context).size.height;
double w = MediaQuery.of(context).size.width;
return Scaffold(
appBar: getAppBar(context, "Back", "", []),
body: SafeArea(
top: true,
bottom: true,
child: Column(
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemCount: 15,
itemBuilder: (context,v){
return
Container(
padding: EdgeInsets.only(left: 15.0,right: 15.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: h*0.2,
width: w*0.4,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(25.0)
),
),
Container(
height: h*0.2,
width: w*0.4,
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.circular(25.0)
),
),
],
),
SizedBox(height: 15.0,),
Divider(
color: Colors.black,
),
SizedBox(height: 15.0,),
],
),
);
}),
)
],
),
),
);
}
Without your code I can't make corrections to the current code. but if you need responsive UI that work regardless of screen size, I suggest you use Rows, Columns with Expanded Widget, as necessary.
for example if you need to have 2 Items inside a Row where each occupies same space you can use,
Row (
children: [
Expanded (
flex:1
child: YourWidget()
),
Expanded (
flex:1
child: YourWidget()
)
]
)
Remember to remove hardcoded size properties along the main axis of your Colum or Row.
Same goes for Columns.
If you need each to have varied sizes, you can use flex property of the Expanded Widget. for example, one items has 1/3 of width and other has 2/3 you can put 1 and 2 as flex values.
more explanation from flutter team: Expanded
I've been trying so hard to build page view system for quotes app. I want the page to flow full screen from top to bottom and bottom to top scrollable/swipe able to navigate between different quotes each time
like this. The scroll will bring new page each time its not casual scroll. I haven't found any guide regarding this on internet so far.
I don't know about how to build it, nothing is popping in my mind for days now. I've tried pageview with gesture detector for swiping up and down, it doesn't works as desired and appbar is static too and the bottom containers as well I don't want this. What I want is the page/screen to flow under the appbar or even a button on top right corner and under 2 buttons on the bottom.
Create a column of Containers where each Container's height and width equals the height and width of the screen. You can do that by using:
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
Also, make sure to wrap your code with a SingleChildScrollView widget to scroll vertically.
Here's the code:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text('Quote number one')),
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(
icon: Icon(Icons.favorite), onPressed: () {})
],
),
)
],
),
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
Text('Quote number two'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(icon: Icon(Icons.share), onPressed: () {}),
IconButton(icon: Icon(Icons.favorite), onPressed: () {})
],
)
],
),
)
],
),
),
),
);
}
}
You can use PageView to get this type of view
Drive Video link
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
PageView pageView;
List<String> quotes = [
'#Quote 1\n\n“I\'m selfish, impatient and a little insecure. I make mistakes, I am out of control and at times hard to handle. But if you can\'t handle me at my worst, then you sure as hell don\'t deserve me at my best.” ',
'#Qoute 2\n\nSo many books, so little time.',
'#Quote 3\n\n A room without books is like a body without a soul'
];
#override
void initState() {
super.initState();
pageController = PageController();
final _quotes = List.generate(quotes.length, (index) => quoteWidget(index));
pageView = PageView(
children: _quotes,
controller: pageController,
scrollDirection: Axis.vertical,
);
}
Widget quoteWidget(int index) {
return Scaffold(
backgroundColor: Colors.black,
body: Column(
children: [
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Text(
quotes[index],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w300,
color: Colors.white,
),
),
),
),
),
Expanded(
flex: 1,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.share),
),
const SizedBox(width: 20),
FloatingActionButton(
onPressed: () {},
child: Icon(Icons.favorite_border),
),
],
),
),
Expanded(child: Container())
],
),
);
}
#override
void dispose() {
pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
brightness: Brightness.dark,
title: Text(widget.title),
),
body: SafeArea(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
pageView,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
RaisedButton.icon(
icon: Icon(Icons.menu_book),
label: Text('General'),
onPressed: () {},
),
const Spacer(),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.color_lens),
),
Container(
width: 50,
height: 50,
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Icon(Icons.person),
),
],
),
)
],
),
),
);
}
}
I'm looking to create a custom bar app like the image below
Image - custom bar app I want
However I am not able to leave the bottom of the menu drawer white, nor align my text to the left, and it is getting like this
Image - my custom app bar
My code
return Scaffold(
appBar: AppBar(
actions: <Widget>[
Stack(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Hi'),
Text('#Name'),
],
),
SizedBox(
width: 10,
),
CircleAvatar(backgroundColor: Colors.white),
SizedBox(
width: 8,
),
CircleAvatar(
backgroundColor: Colors.white,
),
SizedBox(
width: 16,
),
],
),
],
),
],
),
body: Container(),
drawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: Text('Name'),
accountEmail: Text('Email'),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.black,
child: Text('N'),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
)
],
),
),
);
This is a working example. You just have to customize it
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//centerTitle: true,
title: Column(
children: <Widget>[
Text("Hola "),
Text("Senior"),
],
),
leading: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Material(
elevation: 0,
borderRadius: BorderRadius.only(
topRight: Radius.circular(16),
bottomRight: Radius.circular(16),
),
color: Colors.yellow,
child: Icon(Icons.menu)),
),
actions: [
CircleAvatar(
backgroundColor: Colors.white,)
]
),
body: Center(
child : Text('Content')
)
);
}
}
I want make a button with text and icon inside it, with custom background color and custom width. with fix position (not scrollable). would you like to help me please ?
here are the code:
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.shifting,
currentIndex: 0, // this will be set when a new tab is tapped
items: [
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle), title: Text('Players'),backgroundColor: Colors.red),
BottomNavigationBarItem(icon: Icon(Icons.whatshot), title: Text('Trending'),backgroundColor: Colors.blueAccent),
BottomNavigationBarItem(icon: Icon(Icons.access_time), title: Text('Highlights'),backgroundColor: Colors.yellow)
]
its only give a color for the icon.
this is what I want:
Here you go
Widget build(context) {
return Scaffold(
bottomNavigationBar: Container(
height: 56,
margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
children: <Widget>[
Container(
width: 66,
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Icon(Icons.chat, color: Colors.white), Text("CHAT", style: TextStyle(color: Colors.white))],
),
),
Container(
width: 66,
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Icon(Icons.notifications_active, color: Colors.white), Text("NOTIF", style: TextStyle(color: Colors.white))],
),
),
Expanded(
child: Container(
alignment: Alignment.center,
color: Colors.red,
child: Text("BUY NOW", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
),
),
],
),
),
);
}
You may want to look at the concept of a BottomAppBar instead.
This bar accepts any widget as children not just BottomNavigationBarItems.
You could try this:
BottomAppBar(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: SizedBox(
height: 44,
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.add, color: Colors.blue, size: 24),
Text("Add")
],
),
),
),
),
),
]
),
)