Flutter:如何解决“像素溢出的RenderFlex”错误?

Pea*_*Gen 5 android dart flutter flutter-layout

GridView在我的Flutter应用程序中用于显示图像及其标题。请检查以下代码。

import 'package:flutter/material.dart';

import '../common_ui/search_bar.dart';

class PurchaseProductsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return PurchaseProductsUI();
  }
}

class PurchaseProductsUI extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _PurchaseProductUIState();
  }
}

class _PurchaseProductUIState extends State<PurchaseProductsUI> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ListView(
      children: <Widget>[
        Container(
          margin: EdgeInsets.all(20),
          child: SearchBar(),
        ),
        Container(
            margin: EdgeInsets.all(20),
            child: GridView.builder(
                physics: ScrollPhysics(), // to disable GridView's scrolling
                shrinkWrap: true,
                itemCount: 20,
                gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2),
                itemBuilder: (BuildContext context, int index) {
                  return Container(
                      padding: EdgeInsets.all(5), child: _buildImageBoxes());
                })),
      ],
    );
  }

  Widget _buildImageBoxes() {
    return 
   Column(
      children: <Widget>[
        Container(
          child: Image.network("https://picsum.photos/200/300/?random"),
        ),
        Container(
          padding: EdgeInsets.all(10),
          child:  Text("Text"),        )
      ],
    );

  }
}
Run Code Online (Sandbox Code Playgroud)

运行上面的代码时出现以下错误和UI

I/flutter ( 2743): ??? EXCEPTION CAUGHT BY RENDERING LIBRARY ??????????????????????????????????????????????????????????
I/flutter ( 2743): The following message was thrown during layout:
I/flutter ( 2743): A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): The overflowing RenderFlex has an orientation of Axis.vertical.
I/flutter ( 2743): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
I/flutter ( 2743): black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
I/flutter ( 2743): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
I/flutter ( 2743): RenderFlex to fit within the available space instead of being sized to their natural size.
I/flutter ( 2743): This is considered an error condition because it indicates that there is content that cannot be
I/flutter ( 2743): seen. If the content is legitimately bigger than the available space, consider clipping it with a
I/flutter ( 2743): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
I/flutter ( 2743): like a ListView.
I/flutter ( 2743): The specific RenderFlex in question is:
I/flutter ( 2743):   RenderFlex#4a1bb OVERFLOWING
I/flutter ( 2743):   creator: Column ? Padding ? Container ? RepaintBoundary-[<14>] ? IndexedSemantics ?
I/flutter ( 2743):   NotificationListener<KeepAliveNotification> ? KeepAlive ? AutomaticKeepAlive ? SliverGrid ?
I/flutter ( 2743):   MediaQuery ? SliverPadding ? ShrinkWrappingViewport ? ?
I/flutter ( 2743):   parentData: offset=Offset(5.0, 5.0) (can use size)
I/flutter ( 2743):   constraints: BoxConstraints(w=150.0, h=150.0)
I/flutter ( 2743):   size: Size(150.0, 150.0)
I/flutter ( 2743):   direction: vertical
I/flutter ( 2743):   mainAxisAlignment: start
I/flutter ( 2743):   mainAxisSize: max
I/flutter ( 2743):   crossAxisAlignment: center
I/flutter ( 2743):   verticalDirection: down
I/flutter ( 2743): ????????????????????????????????????????????????????????????????????????????????????????????????????
I/flutter ( 2743): ????????????????????????????????????????????????????????????????????????????????????????????????????
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
I/flutter ( 2743): Another exception was thrown: A RenderFlex overflowed by 111 pixels on the bottom.
Reloaded 0 of 446 libraries in 1,179ms.
Run Code Online (Sandbox Code Playgroud)

下面是UI

在此处输入图片说明

我该如何解决?

小智 53

尝试在 _buildImageBoxes() 函数中使用 Expanded 而不是 Container

  Widget _buildImageBoxes() {
    return Column(
      children: <Widget>[
        Expanded(
          child: Image.network("https://picsum.photos/500/500/?random"),
        ),
        Container(
          padding: EdgeInsets.all(10),
          child: Text("Text"),
        )
      ],
    );
  }
Run Code Online (Sandbox Code Playgroud)


Bak*_*ker 7

Expanded? 计算空间

ExpandedFlexible小部件ColumnRow将使 Flutter 计算剩余空间并使用该空间进行布局。

窗口小部件不在ExpandedFlexible正在布局,无论屏幕/约束的空间


为什么/这是如何工作的

ColumnRow分为两个主要阶段:

  1. Flexible项目
  2. Flexible项目(ExpandedFlexible小部件)

阶段1

Flutter 执行阶段 1 时没有考虑屏幕尺寸或任何其他限制。

Flutter 只是将所有非 flex-factor 项目大小加在一起。

屏幕或其他限制的总和太大?? RenderFlex overflowed例外。

阶段2

带有flex构造函数参数的小部件是 flex-factor 项目。

FlexibleExpanded小部件。(Spacer也是,但没有人使用它。)

在第 1 阶段之后,任何 flex-factor 小部件的布局都考虑到了剩余空间


非灵活和弹性因子布局阶段之间的主要区别

  • 非弹性布局?不分空间
  • 弹性因子布局 ? 使用剩余空间

Columnor 中Row,将小部件包装在Expandedor 中Flexible,Flutter 将计算其布局的剩余空间。这将防止问题中出现RenderFlex overflowed异常,因为每个Image小部件都会根据空间限制调整自己的大小

但在第一阶段,没有空间限制。所以Images没有调整大小(和溢出)。

儿童小部件内ColumnRow 裹在ExpandedFlexible将在其固有的大小进行布局,无论屏幕/约束的空间。

Space 400
  Column
    Image 150
    Image 150
    Image 150
Run Code Online (Sandbox Code Playgroud)

总和非弹性图像:450。可用空间:400? Overflowed

解决方案:使用第 2 阶段?使用计算空间

包装Image在 flex widget 中Expanded计算可用高度,然后在(作为约束)之间共享ExpandedImage调整大小以适应内部Expanded约束:

Space 400
  Column
    Expanded 133
      ? Image ?
    Expanded 133
      ? Image ?
    Expanded 133
      ? Image ?
Run Code Online (Sandbox Code Playgroud)

Sum flex Expandeds:399。空间:400? OK


小智 5

Widget build(BuildContext context) {

    final _screenSize = MediaQuery.of(context).size;

    return Container(
      height: _screenSize.height * 0.2,);
}                                                                                     
Run Code Online (Sandbox Code Playgroud)

MediaQuery.of(context)它对我有用!