dart Flutter -下拉按钮溢出

4ioopgfo  于 12个月前  发布在  Flutter
关注(0)|答案(9)|浏览(103)

我正在试验Flutter,目前正在尝试在对话框的列表视图中显示输入字段和下拉列表。然而,我得到的下拉溢出的水平宽度的看法,并导致黄灰色条纹图案(如下所示)


ListView中DropdownButton小部件溢出
代码为:

class DataInput extends StatefulWidget {

      @override
      State createState() => new DataInputState("");
    }

    enum DismissDialogAction {
      cancel,
      discard,
      save,
    }

    class DataInputState extends State<DataInput> {
      final String _data;
      static const types = const <Map<String, String>>[
        const {
          "id": "103",
          "desc": "0001 - lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum"
        },
        const {
          "id": "804",
          "desc": "0002 - lorem ipsum lorem ipsum"
        },
      ];

      DataInputState(this._data);

      @override
      Widget build(BuildContext context) {
        final ThemeData theme = Theme.of(context);
        return new Scaffold(
          appBar: new AppBar(
            title: const Text("Details"),
            actions: <Widget>[
              new FlatButton(
                  onPressed: () => Navigator.pop(context, DismissDialogAction.save),
                  child: new Row(
                    children: <Widget>[
                      new Icon(Icons.save, color: Colors.white,),
                      new Text(
                          "Save",
                          style: theme.textTheme.body1.copyWith(
                            color: Colors.white,)
                      )
                    ],
                  )
              ),
            ],
          ),
          body: new ListView(
            shrinkWrap: true,
            children: <Widget>[
              new Text("Set Label"),
              new TextField(
                autocorrect: false,
              ),
              new Text("Select Type"),
              new Container(
                width: new FractionColumnWidth(0.5).value,
                child: new DropdownButton(
                    items: types.map((m) =>
                    new DropdownMenuItem(
                        key: new Key(m["id"]),
                        child: new Text(m["desc"]))
                    ).toList(growable: false),
                    onChanged: null
                ),
              ),
            ],
          ),
        );
      }
    }

错误代码:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
    The following message was thrown during layout:
    A horizontal RenderFlex overflowed by 433 pixels.

    The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
    black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
    RenderFlex to fit within the available space instead of being sized to their natural size.
    This is considered an error condition because it indicates that there is content that cannot be
    seen. If the content is legitimately bigger than the available space, consider clipping it with a
    RectClip widget before putting it in the flex, or using a scrollable container rather than a Flex,
    for example using ListView.
    The specific RenderFlex in question is:
    RenderFlex#cc264 relayoutBoundary=up12 OVERFLOWING
    creator: Row ← SizedBox ← DefaultTextStyle ← Stack ← Listener ← _GestureSemantics ←
    RawGestureDetector ← GestureDetector ← DropdownButton ← ConstrainedBox ← Container ←
    RepaintBoundary-[<3>] ← ⋯
    direction: horizontal
    mainAxisAlignment: space-between
    mainAxisSize: min
    crossAxisAlignment: center
    textDirection: ltr
    verticalDirection: down

我尝试了以下几种方法,但都不起作用:

  • 将下拉框 Package 在Row、Column、Padding和ClipRect中

有人能帮助我理解这个问题并告诉我如何解决它吗?

更新使用FittedBox可以防止溢出,但文本大小会缩小到难以辨认。

7dl7o3gd

7dl7o3gd1#

我认为你遇到了一个合法的错误与DropDownButton本身。这里有一个关于这个问题的Github问题:https://github.com/flutter/flutter/issues/9211
如果你需要立即修复,你实际上可以自己修补DropDownButton!为此:
1.从Flutter Framework中打开dropdown.dart并将其粘贴到您自己的项目中作为fixed_dropdown.dart
1.从这个文件中删除DropDownMenuItem类,这样它就不会与您的正常Flutter导入发生冲突
1.将DropDownButton重命名为FixedDropDownButton,这样它就不会与Flutter导入冲突
1.导航到_DropdownButtonStatebuild方法。在Row中找到IndexedStack。使用Expanded小部件 Package IndexedStack
我在Github Issue本身上发布了这个信息,如果你想看到修复的效果,也可以在那里找到这个解决方案的截图!

qlvxas9a

qlvxas9a2#

上述方法都不能很好地解决这个问题。
请尝试FittedBox作为documented here
就像这样 Package DropdownMenuItem子项

DropdownMenuItem<MyDropdownContentClass>(
            child: FittedBox(
              child: Text("dropdown item display"),
              fit: BoxFit.contain,
            ),
          );

它会在绘制过程中自动调整整个小部件的大小,也就是你的Text()。

c6ubokkw

c6ubokkw3#

如果你使用的是一行,为了让它起作用,你必须将行子元素设置为Expanded,并将DropdownButtonisExpanded属性设置为:

Row(
    children: <Widget>[
      Expanded(
        child: DropdownButton<String>(
          isExpanded: true, 
          value: _selectedLanguageNative,
          items: list,
          hint: Text(LanguageLocal.getDisplayLanguage(
              Localizations.localeOf(context).languageCode)["name"]),
          onChanged: (String value) {
            print(value);
            setState(() {
              _selectedLanguageNative = value;
            });
          },
        ),
      ),
    ],
  ),
vaqhlq81

vaqhlq814#

详细说明ganapat答案,您可以通过以下方式设置列表:

final dropdownItems = _list
        .map((String item) => new DropdownMenuItem<String>(
              value: item,
              child: new SizedBox(width: 200.0, child: new Text(item)),
            ))
        .toList();
lfapxunr

lfapxunr5#

我为此苦苦挣扎,最终找到了一个完美的解决方案来解决@Dah提出的问题。在Github issue Look at Sep 18, 2019中有提示:使用DropDownButton的selectedItemBuilder属性。这里还有一个很好的工作示例Flutter Docs。我包括了一段代码,它只是在下拉按钮关闭时用省略号代替长文本。它通过使用selectedItemBuilder返回的Text()小部件来实现,它允许溢出属性设置省略号:

child: DropdownButton<String>(
        isExpanded: true,
        hint: Text('Select Faculty'),
        value: selectedFaculty,
        underline: Container(
          height: 0,
        ),
        onChanged: (String value) async {
          selectedFaculty = value;
        },
        selectedItemBuilder: (BuildContext context) {
          return dropFaculty.map<Widget>((String text) {
            return Text(
              text,
              overflow: TextOverflow.ellipsis,
            );
          }).toList();
        },
        items: disableKeyFields || selectedInstitution == null
            ? null
            : dropFaculty.map((String faculty) {
                return DropdownMenuItem<String>(
                  value: faculty,
                  child: Text(
                    faculty,
                    style: TextStyle(color: Colors.black),
                  ),
                );
              }).toList(),
      ),
yjghlzjz

yjghlzjz6#

谢谢brianegan的回答。
在步骤3之后,查看class _DropdownMenuRouteLayout:

@override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    // The maximum height of a simple menu should be one or more rows less than
    // the view height. This ensures a tappable area outside of the simple menu
    // with which to dismiss the menu.
    //   -- https://material.io/design/components/menus.html#usage
    final double maxHeight =
        math.max(0.0, constraints.maxHeight - 2 * _kMenuItemHeight);
    // The width of a menu should be at most the view width. This ensures that
    // the menu does not extend past the left and right edges of the screen.
    final double width = math.min(constraints.maxWidth, buttonRect.width);
    return BoxConstraints(
      minWidth: width,
      maxWidth: width,
      minHeight: 0.0,
      maxHeight: maxHeight,
    );
  }

你可以用你自己的方式实现'maxWith'。

cqoc49vn

cqoc49vn7#

最简单的解决方案是将isExpanded属性添加到DropdownButton中的true
举例来说:

new DropdownButton(
                  isExpanded: true, //Adding this property, does the magic
                  items: [
                    new DropdownMenuItem(
                        child: Text("Some large text that needs to be wrapped or ellipsized", 
                        overflow: TextOverflow.ellipsis),
                    ),
                    new DropdownMenuItem(
                      child: Text("This is another large text that needs to be wrapped or ellipsized", 
                      overflow: TextOverflow.ellipsis),
                    ),
                    new DropdownMenuItem(
                      child: Text("And one more large text that needs to be wrapped or ellipsized", 
                      overflow: TextOverflow.ellipsis),
                    )
                  ],
                  onChanged: (val) {
                    //print(val);
                  }),
s8vozzvw

s8vozzvw8#

我设法解决了这个问题,将DropdownMenuItem的子项 Package 在SizedBox中,并给SizedBox一个固定的宽度,这样就不会溢出UI,而且看起来仍然很好。
eg.

new DropdownMenuItem<String>(
                      value: value,
                      child:  new SizedBox(
                        width: 200.0,
                        child: new Text('Long text with ${value} ')
                      ),
                    )
lnvxswe2

lnvxswe29#

尝试使用isExpanded: true,

它会自动将文本扩展到新行

DropdownButton(
     isExpanded: true, //Add this property
     items: [
          DropdownMenuItem(
              child: Text("Your Text Here", 
              overflow: TextOverflow.ellipsis),
          ),
}),

参考下图
没有足够的空间在一行中输入文本,因此继续下一行

相关问题