删除 DropdownButton 的文本和尾部图标之间的空 Space

Remove Empty Space between Text and Trailer Icon of DropdownButton

我有一个显示字符串列表的下拉菜单。字符串的值包含仅由四个字母组成的单词和由许多字母组成的单词。当所选项目是具有四个字母的项目时,这会产生布局问题。在文本和下拉按钮的尾随图标之间可以看到一个空的或白色的 space。这个空space怎么去掉?如何根据所选值调整下拉按钮的大小?

文本和尾随图标之间的空白 Space 照片:

列表:

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

下拉菜单:

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

你不能。如果你看一下代码

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

克隆小部件并在必要时将其更改为您的要求(不推荐,因为下划线代码更改时您必须维护它)。

作为一个选项,您可以基于 PopupMenuButton 而不是常规的 DropdownButton

构建它

下面是一个例子

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;
        });
      },
    );
  }
}

另一种解决方法是将其设为可点击的文本,将下拉选项显示为对话框。这是一个例子:

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,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

使用 flexfit.loose 时,下拉按钮(来自此小部件内的堆栈)中剩余的 space 将被剪切

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 [],
        ),
      ),
    ),
  ),
),
])