简体   繁体   中英

How do I make widgets reusable in Flutter?

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(),
  );
}

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;
            });
          }),
    ]);
  }

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;
    });
  },
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM