0

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(),
  );
}
koopmac
  • 936
  • 10
  • 27

2 Answers2

1

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;
    });
  },
);
DAG
  • 6,710
  • 4
  • 39
  • 63
  • Thanks for the answer, except the code returns `There should be exactly one item with [DropdownButton]'s value: one. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value` Also, change `DropDownMenuItem` to `DropdownMenuItem` and remove `` assignment from `items` list. – koopmac Mar 10 '20 at 06:22
0

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;
            });
          }),
    ]);
  }
Kahou
  • 3,200
  • 1
  • 14
  • 21