I have two dropdown buttons that are mutually exclusive. How can I clear (or set) the value of one when the other is set?
Thanks
for 1st dropdown:
onChanged: (String newValue) {
setState(() {
dropdownValueFirst = newValue;
dropdownValueSecond = "Bangladesh";
});
},
for 2nd dropdown:
onChanged: (String newValue) {
setState(() {
dropdownValueSecond = newValue;
dropdownValueFirst ="One";
});
},
See below code:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String dropdownValueFirst="One";
String dropdownValueSecond="Bangladesh";
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<String>(
value: dropdownValueFirst,
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(() {
dropdownValueFirst = newValue;
dropdownValueSecond = "Bangladesh";
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
),
const Padding(padding: EdgeInsets.only(left: 8)),
DropdownButton<String>(
value: dropdownValueSecond,
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(() {
dropdownValueSecond = newValue;
dropdownValueFirst ="One";
});
},
items: <String>['Bangladesh', 'India', 'China']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
When 1st drop down in pressed then try to reset value of 2nd dropdown inside setState on onChanged event and vice versa,
onChanged: (String newValue) {
setState(() {
dropdownValueFirst = newValue;
dropdownValueSecond='Initial Value of second',// remeber this value must be same as initial value of 2nd dropdown =>value: 'Initial Value of second',
});
},
Related
I have a simple DropDownButton and would like to disable/hide the downward pointing arrow that is attached to it but there doesn't seem to be an option for it?
A very hacky workaround is to set a custom icon and give it a transparent color but that really does not feel like a good solution.
add iconSize: 0.0 to your DropdownButton like this
DropdownButton(
iconSize: 0.0,
...
)
Make use of the Visibility widget like this -
icon: Visibility (visible:false, child: Icon(Icons.arrow_downward)),
See the complete code below:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
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: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Visibility (visible:false, child: Icon(Icons.arrow_downward)),
iconSize: 24,
elevation: 16,
style: const 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(),
);
}
}
The best way is to defined an empty Widget as icon.
An empty Widget can be set with SizedBox.shrink(), so you need to add icon: SizedBox.shrink(), to your DropdownButton parameters.
Here a quick example :
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
elevation: 16,
icon: SizedBox.shrink(),
style: const 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(),
);
}
}
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
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: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 15,
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(),
);
}
}
You can add width: (specification) and height: (specification) in your dropdown list. Specification -> number.
Please, use the Code Sample formatting option.
you can do it like this :
return Container(
child: DropdownButton(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 15,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: ['One', 'Two', 'Free', 'Four'] .map<DropdownMenuItem>((String value) {
return DropdownMenuItem(
value: value,
child: Container(
height: 100,
width: 200,
alignment: Alignment.centerLeft,
child: Text(value)
)
);
}).toList(),
)
);
Btw, please use the Code Sample formatting option.
I have a very simple list of maps.
List<Map<String, String>> items = [
{ 'a': 'Some Text' },
{ 'b': 'Another Text' },
];
I want to map the above list to a dropdown list.
DropdownButton<String>(
hint: Text('Select a value'),
items: items.map((item) {
return DropdownMenuItem<String>(
value: // how to get key here a, b
child: // how to get value 'Some Text', 'Another Text'
);
}).toList(),
onChanged: (String newValue) {
setState(() {
// ...
});
},
),
)
How to get the key of the map, item has a property keys but not key and values and not value.
For this particular input:
List<Map<String, String>> items = [
{ 'a': 'Some Text' },
{ 'b': 'Another Text' },
];
You can do a workaround by accessing all the keys/values using getters and locating its very first element like this.
DropdownButton<String>(
items: items.map((item) {
return DropdownMenuItem<String>(
value: item.keys.first,
child: Text(item.values.first),
);
}).toList(),
onChanged: (value){},
)
You can copy paste run full code below
You need to use DropdownButton<Map<String, String>>
You can adjust Text("${value.keys.first} ${value.values.first}") per your request
code snippet
DropdownButton<Map<String, 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: (Map<String, String> newValue) {
setState(() {
dropdownValue = newValue;
print(
"${dropdownValue.keys.first} ${dropdownValue.values.first}");
});
},
items: items.map<DropdownMenuItem<Map<String, String>>>(
(Map<String, String> value) {
return DropdownMenuItem<Map<String, String>>(
value: value,
child: Text("${value.keys.first} ${value.values.first}"),
);
}).toList(),
),
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Map<String, String>> items = [
{'a': 'Some Text'},
{'b': 'Another Text'},
];
Map<String, String> dropdownValue;
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<Map<String, 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: (Map<String, String> newValue) {
setState(() {
dropdownValue = newValue;
print(
"${dropdownValue.keys.first} ${dropdownValue.values.first}");
});
},
items: items.map<DropdownMenuItem<Map<String, String>>>(
(Map<String, String> value) {
return DropdownMenuItem<Map<String, String>>(
value: value,
child: Text("${value.keys.first} ${value.values.first}"),
);
}).toList(),
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
DropdownButton doesn't reflect menuItem's changes when the dropdown menu is open.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
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: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final disabledItems = ['Free', 'Four'];
List<String> items = ['One', 'Two', 'Free', 'Four'];
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) {
if (!disabledItems.contains(newValue)) {
setState(() {
dropdownValue = newValue;
});
}
},
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Row(children: [
Text(
value,
style: TextStyle(
color: disabledItems.contains(value) ? Colors.grey : null,
),
),
IconButton(
icon: Icon(Icons.delete),
color: Colors.black38,
onPressed: () {
setState(() {
items.removeWhere((element) => element == 'Two');
});
print(items.length);
},
)
]),
);
}).toList(),
);
}
}
What I aim is the chance of removing an item from the menu when the delete icon is pressed. All the expected events are working as expected and the DropDown items list is updating accordingly in the backend but it doesn't re-render.
DorpDown Menu with delete icon
In order to be able to see the updated items list I have to close the dropdown menu and open it again but this doesn’t feel right in terms of user experience.
I just created a simple flutter app with two DropdownButtonFormField widgets.
And I want to update both widgets if first one is selected.
Expectation:
select number from the first dropdown menu
same number appears in the second dropdown
Result:
- select number from the first dropdown menu
- only the first dropdown menu is updated
Can somebody please tell me what I am doing wrong when calling setState onChaged method of the first dropdown menu widget?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
List<int> myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
int currentNumber = 1;
int anotherNumber = 9;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
DropdownButtonFormField<int>(
value: currentNumber,
items: myList.map((int value) {
return DropdownMenuItem<int>(
value: value,
child: Container(
width: 200,
child: Text(
value.toString(),
),
),
);
}).toList(),
onChanged: (int newValue) {
setState(() {
currentNumber = newValue;
anotherNumber = newValue;
});
},
),
DropdownButtonFormField<int>(
value: anotherNumber,
items: myList.map((int value) {
return DropdownMenuItem<int>(
value: value,
child: Container(
width: 200,
child: Text(
value.toString(),
),
),
);
}).toList(),
onChanged: (int newValue) {
setState(() {
anotherNumber = newValue;
});
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}}