5

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,
            ),
          )),
CoderUni
  • 5,474
  • 7
  • 26
  • 58

6 Answers6

17

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

2

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,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Texv
  • 1,225
  • 10
  • 14
1

Checkout DropdownButton2

There is a customButton property. An example of how I've used it.

 customButton: Row(
            children: [
              const Icon(
                Icons.plus_one,
                size: 12,
              ),
              Text(
                "References",
              )
            ],
          ),

The option box expands to fit the size of the row.

EDIT: Upon posting this I realize that its still constrained to not being able to have a smaller box compared to items inside

Screenshot

Josh Pachner
  • 151
  • 6
0

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).

Agreensh
  • 1,305
  • 1
  • 12
  • 15
  • How would I be able to change it to my requirements? Could you provide the code for that? Sorry, I've never edited flutter's code before. I am fine with maintaining it when the underlining code changes. – CoderUni Mar 31 '20 at 08:37
  • https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/dropdown.dart That is the source file, but note that it imports a lot of the material source files. Going down this route will be lots of work (and will "break" material design). – Agreensh Mar 31 '20 at 08:43
  • You're right. It will break a lot of things and the code is pretty long to debug. Thanks for your answer though. – CoderUni Mar 31 '20 at 08:54
0

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 [],
        ),
      ),
    ),
  ),
),
])
Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
0

With property alignment in DropdownButton you can put de Text centerRight and make the desire effect.

Test on Flutter 2.12

DropdownButton<String>(
                  value: dropdownValue,
                  elevation: 16,
                  underline: const SizedBox(),
                  isDense: true,
                  alignment: Alignment.centerRight,
)

enter image description here enter image description here