Flutter(Dart):渲染引起的异常 / RenderFlex溢出

117

我在使用Flutter(Dart)时遇到了RenderFlex溢出像素的问题,这是一个渲染库的异常。

我该如何管理或应用滚动功能到我的应用程序页面视图,以避免Flutter出现以下消息的渲染异常:

A RenderFlex overflowed by 28 pixels on the bottom.

如果您需要完整的日志来帮助我,可以在这里找到:

enter image description here

在热重载时,底部会出现黄黑色条纹,如消息所示。

我能否使用可滚动小部件来解决这个问题?或者我可以以其他方式声明我的小部件以控制它?

如果需要完整代码(我更改了文本数据,但假设出现的文本比屏幕尺寸长,因此会出现错误):

   @override
  Widget build(BuildContext context) {
    return new DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            bottom: new TabBar(
              tabs: [
                new Tab(text: "xxx",),
                new Tab(text: "xxx",),
                new Tab(text: "xxx",),
              ],
            ),
            title: new Text(data["xxx"]),
          ),
          body: new TabBarView(
            children: [
              new Column(
                children: <Widget>[
                  new Text(data["xxx"],
                        style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.blue,
                              fontSize: 16.0
                        ),),
                  new Text(data["xxx"],
                        style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.blue,
                              fontSize: 10.0
                        ),),
                  new Text(data["xxx"],
                        style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.blue,
                              fontSize: 16.0
                        ),),
                  new Text(data["xxx"],
                        style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.blue,
                              fontSize: 8.0
                        ),
                      ),
                  new Text(data["xxx"],
                        style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.blue,
                              fontSize: 8.0
                        ),),

                  new Row(
                    children: <Widget>[
                      new Expanded(
                        child: new Text("xxx"),
                      ),
                      new Expanded(
                        child: new Icon(Icons.file_download, color: Colors.green, size: 30.0,),
                      ),
                    ],
                  ),

                  new Divider(),
                  new Text("xxx", 
                            style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.red,
                              fontSize: 16.0
                      ),
                  ),
                ],
              ),

              new ListView.builder(
                itemBuilder: (BuildContext context, int index) => new EntryItem(_lstTiles[index]),
                itemCount: _lstTiles.length,
              ),

              new Column(
                children: <Widget>[
                  new Text(data["xxx"], 
                            style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.green[900],
                              fontSize: 16.0
                      ),
                  ),
                  new Text(data["xxx"], 
                            style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.green[900],
                              fontSize: 16.0
                      ),),
                  new Text(data["xxx"]),
                  new ListTile(title: new Text("xxx")),
                  new Text(data["xxx"]),
                  new ListTile(title: new Text("xxx")),
                  new Divider(),
                  new Text("xxx", 
                            style: new TextStyle(
                              fontStyle: FontStyle.italic,
                              color: Colors.red,
                              fontSize: 16.0
                      ),
                  ),
                ],
              ),
            ],
          ),
        ),
      );
  }

4
您可以在内容周围放置一个可滚动的小部件,以允许其滚动并防止出错。 - Herohtar
嗨Herohtar,确实如此...今天我正在通过https://docs.flutter.io/flutter/widgets/ListView-class.html解决问题,以提供所需的滚动功能。 - oetoni
9个回答

174

这是一个相当普遍的问题,特别是当您开始在多个设备和方向上测试应用程序时。Flutter的Widget库有一个部分涵盖了各种滚动小部件:

https://flutter.io/widgets/scrolling/

我建议您将整个内容包裹在SingleChildScrollView中,或使用滚动ListView
编辑:这个问题和答案引起了一些关注,所以我想为那些到达这里的人提供更多的帮助。
Flutter SDK团队在SDK代码本身中花费了很多精力来提供良好的文档。了解Flex小部件(Row和Column都是Flex的子类)用于布置其子项的算法的最佳资源之一是伴随该类的DartDoc文档。

https://github.com/flutter/flutter/blob/e3005e6962cfefbc12e7aac56576597177cc966f/packages/flutter/lib/src/widgets/basic.dart#L3724

Flutter网站还包含一个有关构建布局的教程,以及一个交互式代码实验室,介绍如何使用RowColumn小部件。

13
如果你不想让它滚动怎么办?在我的情况下,我有一个卡片 > ScopedModelDescendant > 列 > 容器。我不希望列滚动,但容器溢出了它。有什么建议吗? - forresthopkinsa
8
首先,我会尝试将列(Column)的crossAxisAlignment值设置为stretch或将容器包裹在Expanded小部件中。这将尝试强制其成为正确的大小。如果这不起作用,您需要查看容器的子项并确定哪个子项阻止其达到正确的大小。您还可以尝试使用FittedBox,它可以缩放/裁剪内容以使其适合。 - RedBrogdon
1
@forresthopkinsa 为了防止滚动,请在 SingleChildScrollView 中使用 physics: NeverScrollableScrollPhysics() - SoftWyer
2
SingleChildScrollView 可以使用。顺便说一下,你在 YouTube 上很棒! - live-love
我正在使用listview.builder并且遇到了错误(并发现了原因)..但可能是由于在FutureBuilder之前有一个数据录入的Textfield() -- 尝试将listview包裹未能奏效,但将column包裹则可以奏效.. - Bhikkhu Subhuti
显示剩余3条评论

48

假设您有一个包含100个类似以下方式的的List

final children = List<Widget>.generate(100, (i) => Text('Item $i')).toList();

根据设备屏幕的大小,这些小部件可能会溢出,有几个解决方案来处理它。

  1. 使用包含在SingleChildScrollView中的Column

SingleChildScrollView(
  child: Column(children: children),
)
使用ListView
ListView(
  children: children
)
  • 同时使用 ColumnListView(可以使用 Expanded/Flexible,或在这样做时为 ListView 指定一个固定高度)。

  • Column(
      children: [
        ...children.take(2).toList(), // show first 2 children in Column
        Expanded(
          child: ListView(
            children: children.getRange(3, children.length).toList(),
          ), // And rest of them in ListView
        ),
      ],
    )
    

    使用body: SingleChildScrollView(child: Column(children: children),)解决了底部161像素的RenderFlex溢出问题。 - Mohamed Raza
    扩展的小部件对我很有效 :) - Lojith Vinsuka

    16

    我也曾面临同样的问题,尝试这个...

    resizeToAvoidBottomPadding: false,
    

    正文之前

    编辑 - 1

    resizeToAvoidBottomPadding已经过时

    resizeToAvoidBottomInset: false
    

    1
    这仅适用于您不想滚动的情况。下次请提供更多信息,以将此代码行放入脚手架小部件中。 - Paul
    5
    更新:resizeToAvoidBottomPadding已被废弃。 使用resizeToAvoidBottomInset:false。 - Alfonso Tesone

    2
    如果您正在使用列,可以像这样使用扩展包装内部小部件。
     Expanded( 
            child: Center(
              child: Image(
                image: AssetImage('assets/icons/${menuItem.iconData}'),
              ),
            ),
          ),
    

    1
    你可以在列中的每个容器中使用小部件Expanded,然后使用flex进行正确的调整。

    1
    如果列出现问题,请尝试使用Wrap
    // doesn't pass unit tests
    return Column(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Icon(
          icon ?? Icons.cancel_outlined,
          size: 64.0,
          color: theme.colorScheme.error,
        ),
        Text(
          errorTitle,
          style: theme.textTheme.displayLarge,
          textAlign: TextAlign.center,
        ),
        Text(
          errorDetails,
          style: theme.textTheme.titleLarge,
          textAlign: TextAlign.center,
        ),
        if (onPressedActionButton != null && textActionButton != null)
          ElevatedButton(
            onPressed: onPressedActionButton,
            child: Text(textActionButton!),
          ),
      ],
    );
    
    // passes unit tests
    return Wrap(
      direction: Axis.horizontal,
      alignment: WrapAlignment.center,
      runSpacing: 32,
      children: [
        Icon(
          icon ?? Icons.cancel_outlined,
          size: 64.0,
          color: theme.colorScheme.error,
        ),
        Text(
          errorTitle,
          style: theme.textTheme.displayLarge,
          textAlign: TextAlign.center,
        ),
        Text(
          errorDetails,
          style: theme.textTheme.titleLarge,
          textAlign: TextAlign.center,
        ),
        if (onPressedActionButton != null && textActionButton != null)
          ElevatedButton(
            onPressed: onPressedActionButton,
            child: Text(textActionButton!),
          ),
      ],
    );
    

    0
    对我来说,我在一行子元素中添加了一个文本,但是我从Firebase获取的数据为空。因此,请确保有一些数据传入。

    0

    使用SingleChildScrollView包装列。


    0
    你可以使用PreferredSize小部件来包裹文本。
     bottom: PreferredSize(
                        preferredSize: Size.fromHeight(120.0),
                        child: Column(
                          children: <Widget>[
                            Padding(
                              padding: EdgeInsets.only(
                                  right: 5.0, left: 5.0, bottom: 2.0, top: 2.0),
                              child: Text(
                                hospitalName,
                                textAlign: TextAlign.left,
                                style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    color: Colors.white,
                                    fontSize: 14.0),
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.symmetric(horizontal: 10.0),
                              child: Container(
                                height: 1.0,
                                width: MediaQuery.of(context).size.width,
                                color: Colors.white,
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.only(
                                  top: 2.0, right: 5.0, left: 5.0, bottom: 2.0),
                              child: Text(
                                doctorName,
                                textAlign: TextAlign.left,
                                style: TextStyle(
                                    fontWeight: FontWeight.bold,
                                    color: Colors.white,
                                    fontSize: 14.0),
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.symmetric(horizontal: 10.0),
                              child: Container(
                                height: 1.0,
                                width: MediaQuery.of(context).size.width,
                                color: Colors.white,
                              ),
                            ),
                
                            TabBar(
                              isScrollable: true,
                              tabs: [
                                Tab(
                                  text: "Tab1",
                                ),
                                Tab(text: "Tab2"),
                                Tab(text: "Tab3"),
                              ],
                            ),
                          ],
                        )),
    

    在某些情况下,调整Size.fromHeight(120.0)可以解决渲染问题。 - Ayan Bhattacharjee

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接