32

I want to add icon to left of DropDownButton but can't find a way to do so. What I want to achieve is like this:

enter image description here

I have tried following code but it places icon to right where I don't want it and it also overrides arrow icon:

 `@override
  Widget build(BuildContext context) {
  return Scaffold(
  body: Container(
    margin: EdgeInsets.only(top: 64.0, left: 16.0, right: 16.0),
    color: Colors.white,
    child: DropdownButton(
      icon: Icon(
        Icons.person,
        color: Colors.redAccent,
        size: 20.09,
      ),
      isExpanded: true,
      items: _studentList.map((val) {
        return DropdownMenuItem(
          value: val,
          child: Text(val),
        );
      }).toList(),
      value: _currentSelectedItem,
      onChanged: (value) {
        setState(() {
          _currentSelectedItem = value;
        });
      },
    ),
  ),
);
  }`

Output of above code is like this:

enter image description here

I have also tried to place Icon() and DropDownButton() inside Row() widget but that does not allow the DropDownButton() to expand to full width.

Any help would be appreciated.

Thanks

8 Answers 8

32

Use DropdownButtonFormField as it has decoration property. You can use prefixIcon attribute to set icon on left side.

Example:

DropdownButtonFormField<String>(
         decoration: InputDecoration(
         prefixIcon: Icon(Icons.person),
         ),
         hint: Text('Please choose account type'),
         items: <String>['A', 'B', 'C', 'D'].map((String value) {
         return DropdownMenuItem<String>(
         value: value,
         child: new Text(value),
       );
      }).toList(),
     onChanged: (_) {},
),

Result:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

16

There is no specific attribute for adding icon the way you want but you can always work around your code and find some tweaks. Use the following code which will place you Icon() on top of your DropDownButton() button.

@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
  children: <Widget>[
    Container(
      decoration: BoxDecoration(
        color: Colors.white,
        boxShadow: [
          BoxShadow(
            color: Colors.grey,
            blurRadius: 20.0,
            spreadRadius: 0.5,
            offset: Offset(1.0, 1.0),
          ),
        ],
      ),
      padding: EdgeInsets.only(left: 44.0),
      margin: EdgeInsets.only(top: 64.0, left: 16.0, right: 16.0),
      child: DropdownButton(
        isExpanded: true,
        items: your_list.map(
          (val) {
            return DropdownMenuItem(
              value: val,
              child: Text(val),
            );
          },
        ).toList(),
        value: _currentSelectedItem,
        onChanged: (value) {
          setState(() {
            _currentSelectedItem = value;
          });
        },
      ),
    ),
    Container(
      margin: EdgeInsets.only(top: 80.0, left: 28.0),
      child: Icon(
        Icons.person,
        color: Colors.redAccent,
        size: 20.0,
      ),
    ),
  ],
),
  );
}

3 Comments

Thanks Sameed for answering, I will check and will get back to you ASAP
@Sameed Shah how to call same dropdown on icon click
This answer cannot be accepted because on arrow click dropdown button does not open
5

Remember, everything is a widget, so:

iconSize: 0,
hint: Row(
         children: [
            Container(
                child: Text('Freguesias'),
            ),
            Container(
                child: Icon(Icons.arrow_drop_down),
            ),
          ],
 ),

Comments

1

This may too late. But will helpful for upcoming viewers.

Instead of using DropDownButton, we can use DropDownButtonFormField. Which has a decoration property. With this we can make use of prefixIcon property to add icon to the left side of DropDownButton:

DropDownButtonFormField(
  decoration: InputDecoration(
    prefixIcon: Icon(Icons.person, color: Colors.redAccent),
  ),
  ...
);

Comments

1

try to use decoration property of DropdownButtonFormField and use prefixIcon property.

DropdownButtonFormField(
      isDense: false,
      itemHeight: 48,
      isExpanded: true,
      decoration: InputDecoration(
        prefixIcon: Icon(Icons.question_answer_rounded),//Add this line
        filled: true,
        ...
        ),
        ...
  )
        

This will add an icon at left.

Comments

0

If the icon really should be visually part of the DropDown component, you could go the following route. Its a bit hacky and lacks being responsive but its a start for some more experiments. I added a complete working example so you can copy paste it to a runnable main dart file.

In a nutshell, it uses a Stack layout so the icon is just placed over the dropdown component. Then i padded the Text so that there is space to the left.

void main() => runApp(MyApp());

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: MyStatefulWidget(),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

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

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String dropdownValue = 'One';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          children: <Widget>[
            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: Padding(
                    padding: const EdgeInsets.only(left: 30.0),
                    child: Text("$value"),
                  ),
                );
              }).toList(),
            ),
            Container(
                margin: EdgeInsets.symmetric(vertical: 10),
                child: Icon(Icons.arrow_downward)),
          ],
        ),
      ),
    );
  }
}

1 Comment

Sorry for late comment, I will try and give you my feedback ASAP
-1

Wrapping your icon and dropdown widget inside a row widget, nested inside a container will do the work like below:

body: Container(
    margin: EdgeInsets.only(top: 64.0, left: 16.0, right: 16.0),
    color: Colors.white,
    child: 
    child: Row(
    children: <Widget>[
      Icon(
        Icons.person,
        color: Colors.redAccent,
        size: 20.09,
     ),
     Expanded(
        flex:1,
        child:DropdownButton(
            isExpanded: true,
            items: _studentList.map((val) {
            return DropdownMenuItem(
              value: val,
              child: Text(val),
            );
        }).toList(),
        value: _currentSelectedItem,
        onChanged: (value) {
         setState(() {
           _currentSelectedItem = value;
         });
      },
     ),
    )
  ]  
)

1 Comment

The code should be properly formatted. Also parentheses are not matched currently
-2

Simple way to do this would be to pass child prop to DropdownMenuItem, you can then pass any widget, i have created a row and passed the icon and text in the row :

items: <String>['George Green School', 'George Blue School', 'George Red School', 'George Yellow School']
                .map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Row(
                  children: [
                    Icon(Icons.dangerous),
                    Text(value, style: TextStyle(fontSize : 12),),
                  ],
                ),
              );
            }).toList(),

3 Comments

Best answer is to wrap drop down and icon inside a Row() widget.
Not sure what you mean here, wrapping a icon and the entire dropdown in a row, is going to create one icon and one dropdown, and not one icon per dropdown item.
Exactly, thats what I wanted to achieve, back then I was a beginner so, had many issues but anyways, thanks for commenting

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.