How should I customize DropdownButtons and DropdownMenuItems in Flutter?
Asked Answered
E

11

66

The default DropdownButton with DropdownMenuItems returns a light-grey dropdown. How should I customize the dropdown (e.g. background color, dropdown width)? I can change the style property in both DropdownButton and DropdownMenuItem, like this:

return new DropdownButton(
      value: ...,
      items: ...,
      onChanged: ...,
      style: new TextStyle(
        color: Colors.white,
      ),
    );

but this doesn't change the dropdown's background color.

Should I copy DropdownMenu and extend it? Does Flutter plan to add customization for this widget in the near future?

Enriquetaenriquez answered 2/10, 2017 at 17:23 Comment(0)
C
39

As Collin said, your DropdownMenuItem will follow your ThemeData class. Not only its backgroundColor will match the canvasColor in your ThemeData class, but also it will follow the same TextStyle.

So, for a quick example:

new ThemeData(
        fontFamily: "Encode Sans", //my custom font
        canvasColor: _turquoise, //my custom color
//other theme data)

Furthermore, if you want to control the width of the menu, you can feed its child property a new Container and add the desired width, check the following GIF, I started with width: 100.0 then hot reloaded after changing it to 200.0, notice how the width was manipulated, just make sure you use a suitable width so that you do not get overflow problems later on when you use the menu within a more complex layout.

enter image description here

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title:new Text ("Test"),
      ),
      body: new Center(
        child: new DropdownButton(items: new List.generate(20, (int index){
          return new DropdownMenuItem(child: new Container(
            child: new Text ("Item#$index"),
            width: 200.0, //200.0 to 100.0
          ));
        })
            , onChanged: null)
      ),
    );
  }
}
Chanterelle answered 2/10, 2017 at 18:24 Comment(3)
Do you know if there is a way to override the padding (left and right) for each DropdownMenuItem? The ThemeData doesn't have a padding property. I tried setting my DropdownMenuItem's padding to negative but it's not allowed. Thanks!Enriquetaenriquez
@Enriquetaenriquez ThemeData is about the visuals (coloring, text styling..etc) and not about positioning. I believe you want to center your items in the dropdown, so all you need to do is to wrap the Text widget in the answer within a Center widget. However, if you need to customize the positioning of the items such that they are not centered, you will need to wrap the Text widget inside a Row which is wrapped inside a Padding widget, and then customize the padding property as you want.Chanterelle
You can replace the Row in the previous comment with a Container as well, and you will achieve the same result, if there is anything that is not clear enough, please let me know.Chanterelle
R
94

You can accomplish this by wrapping the DropdownButton in a Theme widget and overriding the canvasColor.

screenshot

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  State createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  int _value = 42;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Theme(
          data: Theme.of(context).copyWith(
            canvasColor: Colors.blue.shade200,
          ),
          child: new DropdownButton(
            value: _value,
            items: <DropdownMenuItem<int>>[
              new DropdownMenuItem(
                child: new Text('Foo'),
                value: 0,
              ),
              new DropdownMenuItem(
                child: new Text('Bar'),
                value: 42,
              ),
            ],
            onChanged: (int value) {
              setState(() {
                _value = value;
              });
            },
          ),
        ),
      ),
    );
  }
}
Rhymester answered 2/10, 2017 at 18:0 Comment(4)
Thank you. I was stuck on this until I found this answer!Dismantle
Thanks for this workaround. It looks like its been an issue for some time: github.com/flutter/flutter/issues/17414Pappose
you can also do data: ThemeData.dark(), in the Theme and it will let you have the white / dark drop down or data: ThemeData.light()Brunella
@Zuriel: you don't even need to do that. You can change the dark or light Theme in the MaterialApp.Hamish
G
69

I was able to change the background for the Dropdown by wrapping it in a Container with the color property set.

Before:

enter image description here

After:

enter image description here

Here's the code:

Define these values in the widget state:

final items = ['One', 'Two', 'Three', 'Four'];
String selectedValue = 'Four';

then use this code

Container(
  padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
  decoration: BoxDecoration(
      color: Colors.white, borderRadius: BorderRadius.circular(10)),

  // dropdown below..
  child: DropdownButton<String>(
      value: selectedValue,
      onChanged: (String newValue) =>
        setState(() => selectedValue = newValue),
      items: items
          .map<DropdownMenuItem<String>>(
              (String value) => DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  ))
          .toList(),

      // add extra sugar..
      icon: Icon(Icons.arrow_drop_down),
      iconSize: 42,
      underline: SizedBox(),
  ),
);
Getaway answered 9/2, 2020 at 8:49 Comment(5)
This is best example what i am looking forCota
It almost saves my day, but in DropdownButtonFormField this covers the validation section too not only the field.Privily
this was the only real solution I could find. First I found this one: #66136353 but this is much more elegant than those 1500 lines of code. Wrapping it in a container I can get rounded edges on the button and the drop down menu list. Its clunky for sure, as I'm simulating what should be possible natively, but sufficient. Thank you!Corky
is there required to define variable - dropdownValueChurchlike
@CrazyMind if you don't define it, the dropdown won't change when an item is selected.Getaway
C
39

As Collin said, your DropdownMenuItem will follow your ThemeData class. Not only its backgroundColor will match the canvasColor in your ThemeData class, but also it will follow the same TextStyle.

So, for a quick example:

new ThemeData(
        fontFamily: "Encode Sans", //my custom font
        canvasColor: _turquoise, //my custom color
//other theme data)

Furthermore, if you want to control the width of the menu, you can feed its child property a new Container and add the desired width, check the following GIF, I started with width: 100.0 then hot reloaded after changing it to 200.0, notice how the width was manipulated, just make sure you use a suitable width so that you do not get overflow problems later on when you use the menu within a more complex layout.

enter image description here

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title:new Text ("Test"),
      ),
      body: new Center(
        child: new DropdownButton(items: new List.generate(20, (int index){
          return new DropdownMenuItem(child: new Container(
            child: new Text ("Item#$index"),
            width: 200.0, //200.0 to 100.0
          ));
        })
            , onChanged: null)
      ),
    );
  }
}
Chanterelle answered 2/10, 2017 at 18:24 Comment(3)
Do you know if there is a way to override the padding (left and right) for each DropdownMenuItem? The ThemeData doesn't have a padding property. I tried setting my DropdownMenuItem's padding to negative but it's not allowed. Thanks!Enriquetaenriquez
@Enriquetaenriquez ThemeData is about the visuals (coloring, text styling..etc) and not about positioning. I believe you want to center your items in the dropdown, so all you need to do is to wrap the Text widget in the answer within a Center widget. However, if you need to customize the positioning of the items such that they are not centered, you will need to wrap the Text widget inside a Row which is wrapped inside a Padding widget, and then customize the padding property as you want.Chanterelle
You can replace the Row in the previous comment with a Container as well, and you will achieve the same result, if there is anything that is not clear enough, please let me know.Chanterelle
W
18

You can do something very simple in the latest version of Flutter.

The DropdownButton class has an inbuilt variable called 'dropdownColor' which can be assigned any color you need directly, without changing any 'ThemeData'. Automatically changes the color of the dropdown menu items as well.

Wellborn answered 21/6, 2020 at 13:59 Comment(1)
I have big application which has more than 50 dropdownbuttonformfield. So I cannot change them one-by-one. Its very time consuming work. Can we do it by adding a global themedata? If yes, please suggest, how can we do. Thanks.Aalii
F
15

If you want the DropdownButton to fill the space that it is in, use the property isExpanded and set it to true

DropdownButton<String>(
   isExpanded: true,
)
Floppy answered 13/3, 2020 at 22:8 Comment(2)
Not relevant to the question.Chyack
I wrapped the dropdownbutton with a container and set the containers colorBreathing
C
15

Use this for color

 DropdownButtonFormField(
              items: null,
              onChanged: null,
              dropdownColor: Colors.red,
            ),
Cormier answered 17/2, 2021 at 9:54 Comment(4)
I have big application which has more than 50 dropdownbuttonformfield. So I cannot change them one-by-one. Its very time consuming work. Can we do it by adding a global themedata? If yes, please suggest, how can we do. Thanks.Aalii
@Aalii you can also create a reusable custom dropdown.Cormier
Thank for your quick reply. Yes, we can develop reusable custom dropdown but we still have to replace it on more than 50 existing dropdownbuttonformfield elements in the app. Thanks for your suggestion :)Aalii
I randomly came across your comment and noticed I needed the FormField one! Thanks :DInterpellant
L
4

https://api.flutter.dev/flutter/material/DropdownButton/style.html will help you to figure out some stylings.

DropdownButton(
  dropdownColor: Colors.grey,
  value: this.repeatType,
  onChanged: (String? value) {
    print(value);
    setState(() {
      this.repeatType = value!;
    });
  },
  selectedItemBuilder: (BuildContext context) {
    return this.repeatTypes.map((String value) {
      return Text(
        this.repeatType,
        style: const TextStyle(color: Colors.white),
      );
    }).toList();
  },
  items: this
      .repeatTypes
      .map((item) => DropdownMenuItem(
            child: Text(
              item,
              style: TextStyle(color: Colors.green),
            ),
            value: item,
          ))
      .toList())
Leatherleaf answered 15/8, 2021 at 1:6 Comment(0)
D
3

You can wrap it with container like this:

Container(
  margin: const EdgeInsets.all(15.0),
  padding: const EdgeInsets.only(left: 10.0, right: 10.0),
  decoration: BoxDecoration(
      color: Colors.white,
      border: Border.all(color: Colors.white)
  ),
  child: DropdownButton(
    dropdownColor: Colors.white,
    style: TextStyle(
      color: Colors.black,
      backgroundColor: Colors.white,
    ),
    value: 'ar',
    items: [
      DropdownMenuItem(child: Text('English'), value: 'en'),
      DropdownMenuItem(child: Text('العربية'), value: 'ar'),
    ],
  ),
)

The output:

enter image description here

Dmz answered 6/6, 2021 at 0:20 Comment(0)
P
2

you can use the dropdown_button2 package. You can use the dropdownDecoration property to customize the dropdown menu appearance. This is the best package I found to fully customize a DropdownButton

Pyroconductivity answered 3/8, 2022 at 15:39 Comment(0)
K
1

To create own custom drop down widget you can use below code value - selected dropdown value items - list of dropdownitem you can pass onChanged - pass function that will be invoked when you select from dropdown

import 'package:flutter/material.dart';

class SDropDown extends StatefulWidget {
  final String value;
  final List<DropdownMenuItem<String>> items;
  final Function(String?)? onChanged;
  const SDropDown[enter image description here][1](
      {Key? key, required this.value, required this.items, this.onChanged})
      : super(key: key);

  @override
  _SDropDownState createState() => _SDropDownState();
}

class _SDropDownState extends State<SDropDown> {
  @override
  Widget build(BuildContext context) {
    ThemeData theme = Theme.of(context);
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 3),
      decoration: BoxDecoration(
          color: Colors.white, borderRadius: BorderRadius.circular(10)),
      child: DropdownButton<String>(
        isExpanded: true,
        value: widget.value,
        items: widget.items,
        onChanged: widget.onChanged,
        underline: const SizedBox(),
        dropdownColor: theme.primaryColor,
        style: const TextStyle(color: Colors.black),
      ),
    );
  }
}
Kaden answered 8/4, 2023 at 17:18 Comment(0)
J
0

It's so simple now, Just use the dropdownColor property inside the DropdownButton widget like this:

DropdownButton(
    dropdownColor: Colors.red,  // here you change the background color
    value: 'Your value',
    items: [ ],
)
Johnniejohnny answered 16/6, 2022 at 11:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.