Ishan Fernando Blogger | Flutter | Android | iOS

Creating a dropdown list in Flutter

3 min read 1113

Create a Dropdown List in Flutter

Dropdowns allow users to select a single value from a list of available values, and they are a common widget in any modern application.

As an example, if you have a form with country selection, there are two widgets that you can use to show those country details. One is the radio button, which allows for selecting a single value. The other option is a dropdown.

In this scenario, a dropdown will be the best widget because you can add a large list of countries, and when the user selects a particular country it shows only that selected country. So, it will give a better user experience to the end user.

In this article, we’ll cover these topics and to give you a better idea about how to create and customize a dropdown in Flutter.

Creating a dropdown

There are mainly two types of widgets that you need to create a dropdown in Flutter.

  1. DropdownButton
  2. DropdownMenuItem

The DropdownButton widget contains several required properties we need to make dropdown functional. The main required property is the item property. The item property accepts a list of DropdownMenuItem widgets, which need to show possible options that can be selected.

In this example, let’s create a dropdown that contains a list of country names. I will create a separate method that will return a list of DropdownMenuItem widgets that contain country names:

List<DropdownMenuItem<String>> get dropdownItems{
  List<DropdownMenuItem<String>> menuItems = [
    DropdownMenuItem(child: Text("USA"),value: "USA"),
    DropdownMenuItem(child: Text("Canada"),value: "Canada"),
    DropdownMenuItem(child: Text("Brazil"),value: "Brazil"),
    DropdownMenuItem(child: Text("England"),value: "England"),
  ];
  return menuItems;
}

Next, create a DropdownButton widget along with an items property and set the method we just created to feed the values to the dropdown. Make sure to create this as a separate stateful widget because we need to change the state of the dropdown in the later stage.

Run the application and you will see a dropdown widget but cannot do any interaction with it.

Now let’s set an initially selected value to the dropdown. The value property of the DropdownButton widget can be used to set the currently selected item, and we can set "USA" as a first selected item:

We made a custom demo for .
No really. Click here to check it out.

class _DropdownItemState extends State<DropdownItem> {
  String selectedValue = "USA";
  @override
  Widget build(BuildContext context) {
    return DropdownButton(
      value: selectedValue,
      items: dropdownItems
      );
  }
}

Creating a Flutter Dropdown

Now you can see that "USA" shows as a selected value. But still, you cannot do any interaction with the dropdown. That’s because we have not yet implemented how the dropdown should behave when changing the value. The next section will explain how to handle those value changes.

Identifying dropdown value changes

The onChange callback can be used to identify the value changes. It will return the selected value, and you can change the state of the dropdown by setting the new value to the dropdown like below:

DropdownButton(
      value: selectedValue,
      onChanged: (String? newValue){
        setState(() {
          selectedValue = newValue!;
        });
      },
      items: dropdownItems
      )

Now you can see the dropdown is working as expected, and you can select a new value from the dropdown.

Identifying dropdown value changes in Flutter

Disabling the dropdown

Setting the onChange to null will disable the dropdown item. If you have set a value property, it shows that value as a selected one even though the dropdown is disabled:

     DropdownButton(
        value: selectedValue,
        style: TextStyle(color: Colors.red,fontSize: 30),
        onChanged: null,
        items: dropdownItems
      )

Disabled Dropdown Showing a Selection

If you want to show a placeholder text when the dropdown is disabled, use the disabledHint property. When using this property, make sure the value property is not set:

DropdownButton(
      disabledHint: Text("Can't select"),
      style: TextStyle(color: Colors.red,fontSize: 30),
      onChanged: null,
      value:null.
      items: dropdownItems
      )

Disabled Dropdown with Placeholder Text

Styling the dropdown

Applying icons

Icons can be applied to a dropdown by setting the icon property of the DropdownButton:

Widget build(BuildContext context) {
    return DropdownButton(
      value: selectedValue,
      icon: Icon(Icons.flag),
      onChanged: (String? newValue){
        setState(() {
          selectedValue = newValue!;
        });
      },
      items: dropdownItems
      );
  }

Dropdown with an Icon

Change dropdown items’ colors

The dropdownColor property will allow you to set a background color for the dropdown items. This will change only the dropdown item’s background color, not the selection button color:

DropdownButton(
      value: selectedValue,
      dropdownColor: Colors.green,
      onChanged: (String? newValue){
        setState(() {
          selectedValue = newValue!;
        });
      },
      items: dropdownItems
      )

Dropdown with Color Change

Change text color and the size

The style property will allow you to change the text-related styling, including color and size. You can use the TextStyle widget to set the text-related styling for dropdown items:

DropdownButton(
      value: selectedValue,
      style: TextStyle(color: Colors.red,fontSize: 30),
      onChanged: (String? newValue){
        setState(() {
          selectedValue = newValue!;
        });
      },
      items: dropdownItems
      )

Dropdown with Red Text Color

DropdownButtonFormField provides more functionalities than the normal DropdownButton widget.
First, if you need to customize the dropdown look and feel, you can set a custom decoration by setting the decoration property of the DropdownButtonFormField widget:

              DropdownButtonFormField(
                decoration: InputDecoration(
                  enabledBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.blue, width: 2),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  border: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.blue, width: 2),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  filled: true,
                  fillColor: Colors.blueAccent,
                ),
                dropdownColor: Colors.blueAccent,
                value: selectedValue,
                onChanged: (String? newValue) {
                  setState(() {
                    selectedValue = newValue!;
                  });
                },
                items: dropdownItems)

In this example, if you want to set a background color, you must first set the filled property of the InputDecoration and set a color to fillColor. Otherwise, it will not show the proper result.

Dropdown Menu with Custom Decoration

Another useful feature in DropdownButtonFormField is inbuilt validation support.

To make this work, you must use this widget inside a Form widget. In this example, it will check whether the dropdown has a value, and if not it, it will show the specified message under the dropdown.

This validation will trigger when the button calls validation like _dropdownFormKey.currentState!.validate():

 class _DropdownItemState extends State<DropdownItem> {
  String? selectedValue = null;
  final _dropdownFormKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
        key: _dropdownFormKey,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            DropdownButtonFormField(
                decoration: InputDecoration(
                  enabledBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.blue, width: 2),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  border: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.blue, width: 2),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  filled: true,
                  fillColor: Colors.blueAccent,
                ),
                validator: (value) => value == null ? "Select a country" : null,
                dropdownColor: Colors.blueAccent,
                value: selectedValue,
                onChanged: (String? newValue) {
                  setState(() {
                    selectedValue = newValue!;
                  });
                },
                items: dropdownItems),
            ElevatedButton(
                onPressed: () {
                  if (_dropdownFormKey.currentState!.validate()) {
                    //valid flow
                  }
                },
                child: Text("Submit"))
          ],
        ));
  }
}

Validation Support in a Flutter Dropdown

Conclusion

The Dropdown widget can be used in your Flutter app to show and select a single value from a large set of options.

If you are using a single dropdown, which does not require validation, you can use DropdownButton.

If you are required to apply validation and if the dropdown comes under the Form widget, it is better to use DropdownButtonFormField because it has more customization along with inbuilt validation support.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Ishan Fernando Blogger | Flutter | Android | iOS

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

Leave a Reply