I am new to using a Dropdownbutton but I copied this code from a material example and the value is not changing when I pick a different category. Im not sure whats going on but the value changes internally when I debug but the displayed text stays at the default setting which is "Choose a goal category".
DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.check_circle_outline),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.blue[300]
),
underline: Container(
height: 2,
color: Colors.blue[300],
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
updateCategory(newValue);
});
},
items: <String>['Choose a goal category', 'Financial', 'Physical', 'Family', 'Mental', 'Social', 'Spiritual', 'Personal']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
),
Replace this.
items : <String>['Choose a goal category', 'Financial', 'Physical', 'Family', 'Mental', 'Social', 'Spiritual', 'Personal']
.map((String dropDownStringItem){
return DropdownMenuItem<String>{
value : dropDownStringItem,
...
}
}).toList(),
I hope to help you
Step 1: declare String dropdownValue; do not set value
Step 2: use hint and set to Text('Choose a goal category')
Step 3: items remove string "Choose a goal category"
code snippet
String dropdownValue;
...
DropdownButton<String>(
hint: Text('Choose a goal category'),
value: dropdownValue,
icon: Icon(Icons.check_circle_outline),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.blue[300],
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>[
'Financial', 'Physical', 'Family', 'Mental', 'Social', 'Spiritual', 'Personal'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Center(
child: DropdownButton<String>(
//isDense: true,
hint: Text('Choose a goal category'),
value: dropdownValue,
icon: Icon(Icons.check_circle_outline),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.blue[300],
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>[
'Financial', 'Physical', 'Family', 'Mental', 'Social', 'Spiritual', 'Personal'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
],
),
);
}
}
Related
how to reset dropdonw to defult value after press button ?
i am trying to press button to reset dropdownmune to its defualt
class drawarScreen extends StatelessWidget {
const drawarScreen({super.key});
#override
Widget build(BuildContext context) {
List<String> list = <String>['One', 'Two', 'Three', 'Four'];
String? dropdownValue;
return Scaffold(
body: Column(children:[
DropdownButton<String>(
hint: Text('moammed'),
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? value) {
// This is called when the user selects an item.
setstate({
dropdownValue = value!;
});
},
items: list.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
},
ElevatedButton(
onPress:(){
setstate({
dropdownValue='';
});
},child: Text("reste");
)
]);
}
}
i am trying to press button to reset dropdownmune to its defualt
resat dropdown menu in flutter
You need to put null value instead of empty string
setstate({
dropdownValue = null ;
});
If you like to have other than null, put it there.
And make sure to have StatefulWidget and variables outside the build method.
Full widget
class drawarScreen extends StatefulWidget {
const drawarScreen({super.key});
#override
State<drawarScreen> createState() => _drawarScreenState();
}
class _drawarScreenState extends State<drawarScreen> {
List<String> list = <String>['One', 'Two', 'Three', 'Four'];
String? dropdownValue;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
DropdownButton<String>(
hint: Text('moammed'),
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? value) {
setState(() {
dropdownValue = value;
});
},
items: list.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
ElevatedButton(
onPressed: () {
setState(() {
dropdownValue = null;
});
},
child: Text("Reset"))
],
),
);
}
}
is there any way I could add a mega menu in flutter? I want something like in https://www.headphonezone.in/ 's appbar, but I couldn't find a package that fits. Are there any packages like this or is it possible to write a custom menu like this?
you can implement a mega menu using a combination of DropdownButton and ExpansionTile
import 'package:flutter/material.dart';
class MyMegaMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: 'Menu',
icon: Icon(Icons.arrow_down),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {},
items: <String>['Menu', 'Home', 'Profile', 'Settings']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
This will create a simple dropdown menu with four options: Menu, Home, Profile, and Settings. To turn this into a mega menu, you can nest multiple ExpansionTile widgets inside the items list, like this:
import 'package:flutter/material.dart';
class MyMegaMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: 'Menu',
icon: Icon(Icons.arrow_down),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {},
items: <String>['Menu', 'Home', 'Profile', 'Settings']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList()
.add(ExpansionTile(
title: Text('Menu'),
children: [
ListTile(
title: Text('Submenu 1'),
),
ListTile(
title: Text('Submenu 2'),
),
],
))
);
}
}
I have a question here, I created an increase button widget in a separate file (component)...
increase_button_widget.dart
import 'package:flutter/material.dart';
class IncreaseButtonWidget extends StatefulWidget {
const IncreaseButtonWidget({super.key});
#override
State<IncreaseButtonWidget> createState() => _IncreaseButtonWidgetState();
}
class _IncreaseButtonWidgetState extends State<IncreaseButtonWidget> {
int _counterValue = 0;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue = val;
});
},
count: _counterValue,
countColor: Colors.blue,
buttonColor: Colors.blue,
progressColor: Colors.blue,
);
}
}
Here I will reuse it more than once in my application...
increase.dart
import 'package:increase/widgets/increase_button_widget.dart';
import 'package:flutter/material.dart';
class MyPassagerClassPage extends StatefulWidget {
const MyPassagerClassPage({super.key});
#override
State<MyPassagerClassPage> createState() => _MyPassagerClassPageState();
}
enum SingingCharacter { economy, business, first }
class _MyPassagerClassPageState extends State<MyPassagerClassPage> {
SingingCharacter? _character = SingingCharacter.economy;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Passager & Class"),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.check_outlined),
tooltip: 'Go to the next page',
onPressed: () {
Navigator.pop(context);
},
),
],
),
body: Column(
children: [
const SizedBox(height: 20),
const Text(
'Passengers',
style: TextStyle(fontSize: 30),
),
const ListTile(
leading: Icon(Icons.accessibility_outlined),
title: Text('Adults'),
subtitle: Text('12+ years'),
trailing: IncreaseButtonWidget(),
),
const ListTile(
leading: Icon(Icons.boy_outlined),
title: Text('Children'),
subtitle: Text('2-11 years'),
trailing: IncreaseButtonWidget(),
),
const ListTile(
leading: Icon(Icons.child_care_outlined),
title: Text('Infants'),
subtitle: Text('Under 2 years'),
trailing: IncreaseButtonWidget(),
),
const DividerWidget(),
const SizedBox(height: 25),
const Text(
'Class',
style: TextStyle(fontSize: 30),
),
ListTile(
title: const Text('Economy'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.economy,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Business'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.business,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('First'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.first,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
const DividerWidget(),
],
),
);
}
}
In this case i used this widget 3 times...
My question is how to get the value of each of these increase buttons separately to be able to get them in a different variable...
Hence, in this case, each of these widgets has input data that I will need later to do another calculation.
Im working on a company project. But I can't simply get the idea of how to implement a basic dropdown button into a function but I can't seem to make the values change in the dropdown function what do you think im doing wrong here's my code:
Widget buildDropdownField({
required String dropdownHeader,
required String dropdownValue,
}) {
return Column(
children: <Widget>[
Text(dropdownHeader),
const SizedBox(
height: 10,
),
//dropdownField
DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['-', 'Geçti', 'Kaldı', 'Belirsiz']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
],
);
}
Wrap with StatefulBuilder it will work.
Widget buildDropdownField(
{required String dropdownHeader, required String dropdownValue}) {
return Column(
children: <Widget>[
Text(dropdownHeader),
const SizedBox(
height: 10,
),
StatefulBuilder(
builder: (_, setDropState) {
return DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setDropState(() {
dropdownValue = newValue!;
});
},
items: <String>['-', 'Geçti', 'Kaldı', 'Belirsiz']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
},
)
],
);
}
Try below code hope its help to you. use StatefulBuilder Refer here
Your dropdown function:
buildDropdownField({
required String dropdownHeader,
required String dropdownValue,
}) {
return Column(
children: <Widget>[
Text(dropdownHeader),
const SizedBox(
height: 10,
),
//dropdownField
StatefulBuilder(builder: (context, StateSetter setState) {
return DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['-', 'Geçti', 'Kaldı', 'Belirsiz']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
})
],
);
}
Your Widget:
buildDropdownField(
dropdownHeader: 'dropdownHeader',
dropdownValue: '-',
),
Result->
Result after selection->
First of all, you shouldn't update the parameter with the new value. It did update the parameter, but the function will still getting the value from it's calling.
I did not know the buildDropdownField function is inside a class or not, but it's okay and I will provide the solutions for both scenarios.
Within the Class
You need to create a variable within a class outside the functions.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _dropDownValue = '-';
Widget buildDropdownField({required String dropdownHeader}) {
return Column(
children: <Widget>[
Text(dropdownHeader),
const SizedBox(
height: 10,
),
//dropdownField
DropdownButton<String>(
value: _dropDownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
_dropDownValue = newValue!;
});
},
items: <String>['-', 'Geçti', 'Kaldı',
'Belirsiz'].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
],
);
}
}
Outside the Class
You need to turn it into Stateful Widget in order for the drop down text to change. Once the dropdown is a stateful widget, you can use the solution above or a callback to make the changes on parent class.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _dropDownValue = '-';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: DropDownWidget(
dropdownHeader: 'Name',
dropdownValue: _dropDownValue,
onChanged: (String? newValue) {
setState(() {
_dropDownValue = newValue!;
});
},
),
),
);
}
}
class DropDownWidget extends StatefulWidget {
final String dropdownHeader;
final String dropdownValue;
final Function(String?)? onChanged;
DropDownWidget({required this.dropdownHeader, required this.dropdownValue, this.onChanged, Key? key}) : super(key: key);
#override
_DropDownWidgetState createState() => _DropDownWidgetState();
}
class _DropDownWidgetState extends State<DropDownWidget> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(widget.dropdownHeader),
const SizedBox(
height: 10,
),
//dropdownField
DropdownButton<String>(
value: widget.dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: widget.onChanged,
items: <String>['-', 'Geçti', 'Kaldı', 'Belirsiz'].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
],
);
}
}
I'm attempting to use the Flutter DropdownMenu with different parameters on the same page, however I'm unsure how to structure the code.
If I want to use a list other than ['One', 'Two', 'Free', 'Four'] how would I setup the widget to take different parameters without having to copy and paste the widget everytime?
This is the sample code from the docs:
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.deepPurple
),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
);
}
Instead creating a function which creates the widget tree, consider creating your own widget for the DropdownButton. This should yield a performance benefit in most cases, see this answer for an explantion why this is the case.
You could create your widget like this:
class MyDropdownButton extends StatelessWidget {
const MyDropdownButton({
Key key,
#required this.value,
#required this.labels,
#required this.onChanged,
}) : super(key: key);
final String value;
final List<String> labels;
final ValueChanged<String> onChanged;
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: value,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.deepPurple
),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: onChanged,
items: Cost [
for (final label in labels)
DropdownMenuItem<String>(
key: ValueKey(label),
value: value,
child: Text(value),
)
],
);
}
}
Then you can use it like this:
return MyDropdownButton(
value: dropdownValue,
labels: ["one", "two", "three"],
onChanged: (label) {
setState(() {
dropdownValue = label;
});
},
);
Create a method that returns a DropdownButton.
Widget createDropdownButton({
String value,
List<String> items,
ValueChanged<String> onChanged,
}) {
return DropdownButton<String>(
value: value,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: onChanged,
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
String dropdownValue1 = 'Two';
String dropdownValue2 = '3';
#override
Widget build(BuildContext context) {
return Column(children: [
createDropdownButton(
value: dropdownValue1,
items: ['One', 'Two', 'Free', 'Four'],
onChanged: (String newValue) {
setState(() {
dropdownValue1 = newValue;
});
}),
createDropdownButton(
value: dropdownValue2,
items: ['1', '2', '3', '4'],
onChanged: (String newValue) {
setState(() {
dropdownValue2 = newValue;
});
}),
]);
}