Search code examples
flutterflutter-ui

Flutter DropdownButtonFormField2 - Manage padding


padding:EdgeInsets.fromLTRB(0, 0, 0, 0)

padding:EdgeInsets.fromLTRB(30, 0, 0, 0)

I have some issues with the padding using DropdownButtonFormField2 in Flutter.

Either I set

menuItemStyleData: const MenuItemStyleData(
  padding: EdgeInsets.fromLTRB(30, 0, 0, 0),
),

but then I have too much padding in the FormField when the item is selected (see picture padding:EdgeInsets.fromLTRB(30, 0, 0, 0)),

or I set

menuItemStyleData: const MenuItemStyleData(
  padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
),

but then the items in the dropdown list have no padding (see picture padding:EdgeInsets.fromLTRB(0, 0, 0, 0)).

I would like to have some left padding for the items in the dropdown list and no additional padding in the form field when the item is selected.

Full code:

DropdownButtonFormField2<String>(
  isDense: true,
  isExpanded: true,
  decoration: InputDecoration(
    prefixIcon: const Icon(
      Icons.transgender_outlined,
      color: Colors.white70,
    ),
    //     labelText: "Hello",
    //    labelStyle: TextStyle(color: Colors.yellow.withOpacity(0.9)),
    filled: true,
    floatingLabelBehavior: FloatingLabelBehavior.never,
    fillColor: Colors.white.withOpacity(0.3),
    border: OutlineInputBorder(
        borderRadius: BorderRadius.circular(30.0),
        borderSide: const BorderSide(width: 0, style: BorderStyle.none)),
    errorStyle: TextStyle(fontWeight: FontWeight.bold, fontSize:16, color: Colors.white),
  ),
  hint: const Text(
    'Select Your Gender',
    style: TextStyle(color: Colors.white),
  ),
  items: genderItems
      .map((item) => DropdownMenuItem<String>(
    value: item,
    child: Text(
      item,
      style: TextStyle(
        fontSize: 16,
        color: Colors.white.withOpacity(0.9),
      ),
    ),
  ))
      .toList(),
  autovalidateMode: AutovalidateMode.onUserInteraction,
  validator: (value) {
    if (value == null) {
      return 'Please select gender.';
    }
    return null;
  },
  onChanged: (value) {
    setState(() {
      _selectedGender = value.toString();
    });
  },
  onSaved: (value) {
    _selectedGender = value.toString();
  },
  buttonStyleData: const ButtonStyleData(
    padding: EdgeInsets.fromLTRB(0, 0, 8, 0),
  ),
  iconStyleData: const IconStyleData(
    icon: Icon(
      Icons.arrow_drop_down,
      color: Colors.white,
    ),
    iconSize: 24,
  ),
  dropdownStyleData: DropdownStyleData(
    padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
    offset: const Offset(0, -20),
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(30),
      color: Colors.white.withOpacity(0.3),
    ),
  ),
  menuItemStyleData: const MenuItemStyleData(
    padding: EdgeInsets.fromLTRB(30, 0, 0, 0),
  ),
),

I tried to combine padding for MenuItemStyleData, DropDownStyleData, and ButtonStyleData, with no luck.


Solution

  • As you've figured out, all of those style settings (ButtonStyleData, DropdownStyleData, MenuItemStyleData) affect both the dropdown menu item and the button display. There's a selectedMenuItemBuilder parameter in MenuItemStyleData but unfortunately this only affects selected item. So currently it seems like there is no way to achieve that by using proper padding options.

    One way to achieve this is to let the MenuItemStyleData has some padding while providing a custom widget to the customButton parameter.

    DropdownButtonFormField2<String>(
      // ...
      menuItemStyleData: const MenuItemStyleData(
        padding: EdgeInsets.fromLTRB(30, 0, 0, 0),
      ),
      customButton: Container(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text(
              _selectedGender.toString(),
              style: TextStyle(color: Colors.white),
            ),
            Icon(Icons.arrow_drop_down, color: Colors.white),
          ],
        ),
      ),
    )
    

    Dropdown screenshot


    You can see a reference of how the default dropdown button is implemented in the source code (dropdown_button2.dart#L727).