Remove Empty Space between Text and Trailer Icon of DropdownButton

Viewed 5083

I have a dropdown that display a list of strings. The values of the strings contain words that only consists of four letters and words that consists of many letters. This gives a layout problem when the selected item is the one with four letters. An empty or white space can be seen between the text and the trailing icon of the dropdown button. How can this be empty space be removed? How do I adjust the size of the dropdown button depending on the value selected?

Photo of Empty Space between text and trailing icon:

enter image description here

List:

List<String> textList = ["test", "this_is_a_long_text"];

Dropdown:

DropdownButtonHideUnderline(
      child: ButtonTheme(
       alignedDropdown: true,
       child: DropdownButton<String>(
        items: textList.map((String dropDownStringItem) {
           return DropdownMenuItem<String>(
                      value: dropDownStringItem,
                      child: Text(dropDownStringItem),
                    );
                  }).toList(),
              onChanged: (String newValueSelected) {
                _onDropDownItemSelected(newValueSelected);
              },
              value: _currentItemSelected,
            ),
          )),
4 Answers

as an option you can build it based on PopupMenuButton instead of regular DropdownButton

below an example

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: AwesomeDropdown()),
      ),
    );
  }
}

class AwesomeDropdown extends StatefulWidget {
  @override
  _AwesomeDropdownState createState() => _AwesomeDropdownState();
}

class _AwesomeDropdownState extends State<AwesomeDropdown> {
  final List<String> textList = ["test", "this_is_a111111_long_text"];
  String _currentItemSelected;

  @override
  void initState() {
    super.initState();
    _currentItemSelected = textList[0];
  }

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<String>(
      itemBuilder: (context) {
        return textList.map((str) {
          return PopupMenuItem(
            value: str,
            child: Text(str),
          );
        }).toList();
      },
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(_currentItemSelected),
          Icon(Icons.arrow_drop_down),
        ],
      ),
      onSelected: (v) {
        setState(() {
          print('!!!===== $v');
          _currentItemSelected = v;
        });
      },
    );
  }
}

enter image description here

Another work around is to make it a clickable text that will show the dropdown options as a dialog. Here is an example:

Preview Gif

import 'package:flutter/material.dart';

class CustomDialogTest extends StatefulWidget {
  @override
  _CustomDialogTestState createState() => _CustomDialogTestState();
}

class _CustomDialogTestState extends State<CustomDialogTest> {
  String _onDropDownItemSelected = '(Choose Option ▼)';

  var textList = [
    'Cat',
    'Dog',
    'Colorfull Unicorn',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        title: Text(
          'Dropdown spacing',
        ),
      ),
      body: Padding(
        padding: EdgeInsets.only(top: 8.0),
        child: Container(
          color: Colors.white,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'I am a ',
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 18,
                  fontWeight: FontWeight.w500,
                ),
              ),
              InkWell(
                onTap: () {
                  showDialog(
                    context: context,
                    child: Dialog(
                      backgroundColor: Colors.blue[100],
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(18.0),
                      ),
                      child: ListView.builder(
                          shrinkWrap: true,
                          itemCount: textList.length,
                          itemBuilder: (context, index) {
                            return GestureDetector(
                              child: Row(
                                children: <Widget>[
                                  Icon(
                                    Icons.arrow_right,
                                    color: Colors.black,
                                  ),
                                  Text(
                                    textList[index],
                                    style: TextStyle(
                                      color: Colors.black,
                                      fontSize: 20.0,
                                    ),
                                  ),
                                ],
                              ),
                              onTap: () {
                                Navigator.pop(context);
                                setState(() {
                                  _onDropDownItemSelected = textList[index];
                                });
                              },
                            );
                          }),
                    ),
                  );
                },
                child: Text(
                  _onDropDownItemSelected,
                  style: TextStyle(
                    color: Colors.blue[900],
                    fontSize: 18,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ),
              Text(
                ' Person',
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 18,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

You can't. If you look at the code

// The width of the button and the menu are defined by the widest
// item and the width of the hint.

Clone the widget and change it to your requirements if you have to (not recommended as you'd have to maintain it when the underlining code changes).

With flexfit.loose the remaining space from the dropdownbutton(comes from a stack inside this widget) will be cutted

Row(
  children: [
    Flexible(
      fit: FlexFit.loose,
      child: Padding(
        padding: const EdgeInsets.all(8),
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
              width: 2,
              color: Theme.of(context).primaryColor,
            ),
          ),
        child: Padding(
          padding: const EdgeInsets.only(left: 8.0, right: 8),
          child: DropdownButton(
            icon: const Icon(Icons.filter_alt),
            underline: Container(),
            hint: const Text(
              'Test',
              style: TextStyle(
                color: Colors.black,
              ),
            ),
          items: const [],
        ),
      ),
    ),
  ),
),
])
Related