Flutter: How to minimize width of DropdownButton

Viewed 7265

The DropdownButton in Flutter sets its width based on the largest DropdownMenuItem from the items it has. That leaves a lot of white space between the item and the arrow if a small item is selected. How do I make the button scale to just fit the selected item's width?

I tried using Expanded, some Flexible stuff and I still can't make it change its width.

DropdownButton(
    value: null,
    hint: Text("Small text"),
    items: ..., //Text widgets that have more text and are larger than the hint
)

I am trying to get rid of that space underlined between the hint and the arrow: enter image description here

5 Answers

The width is actually determined by the widest item provided by the selectedItemBuilder argument (which uses the items if not defined). With this little trick I managed to have it working:

    DropdownButton<T>(
      value: value,
      selectedItemBuilder: (ctx) => [for (final item in items) value], 
      items: items,
      onChanged: (value) => ... update value

The selectedItemBuilder in the example produces a list of repeated items (the one corresponding to the selected value). You will need a stateful widget to handle the value.

Wrap Dropdown button with ButtonTheme and add alignedDropdown = true like:

ButtonTheme(
  alignedDropdown: true,
  child: DropdownButton(...),
)

alignedDropdown will match the menu items' width with buttons. Then we need specific width, so wrap ButtonTheme with SizedBox or Container:

SizedBox(
  width: 25, // Your width for dropdowns
  child: ButtonTheme(...),
)

this works:

new Container(
            padding: const EdgeInsets.fromLTRB(10.0, 5, 10, 0),
            child: new Container(
              padding: const EdgeInsets.fromLTRB(10, 5, 5, 5),
              decoration: new BoxDecoration(
                  color: Colors.white,
                  borderRadius: new BorderRadius.only(
                      topLeft: const Radius.circular(5.0),
                      bottomLeft: const Radius.circular(5.0),
                      bottomRight: const Radius.circular(5.0),
                      topRight: const Radius.circular(5.0))),
              child: new Center(
                  child: new Column(children: [
                new DropdownButton(
                  underline: Text(''),
                  icon: Icon(Icons.keyboard_arrow_down),
                  hint: new Text('Small text'),
                  style: TextStyle(
                    color: Colors.white30,
                  ),
                  isExpanded: true,
                  value: _selectedLocation,
                  onChanged: (String newValue) {
                    setState(() {
                      _selectedLocation = newValue;
                    });
                  },
                  items: _locations.map((String location) {
                    return new DropdownMenuItem<String>(
                      value: location,
                      child: new Text(
                        location,
                        style: TextStyle(
                            color: myColour, fontWeight: FontWeight.bold),
                      ),
                    );
                  }).toList(),
                ),
              ])),
            ))

If I understand your problem correctly then I have also encountered it and I have a solution. Simply make a Wrap widget as the parent of your DropdownButton. It will make the dropdown menu wrap to the size of the value (not sure how it would react with the null value though)

Wrap(children: <Widget>[DropdownButton(
value: null,
hint: Text("Small text"),
items: //Text widgets that have more text and are larger than the hint
)])

to remove under line warp Dropdown with DropdownButtonHideUnderline

Related