简体   繁体   English

Flutter:如何修复“像素溢出的 RenderFlex”错误?

[英]Flutter: How to fix "A RenderFlex overflowed by pixels " error?

I am using GridView in my Flutter app to display images and their titles.我在Flutter应用程序中使用GridView来显示图像及其标题。 Please check the below code.请检查以下代码。

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

  }
}

I get the following error and UI when I run the above code运行上述代码时出现以下错误和 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.

Below is the UI下面是用户界面

在此处输入图片说明

How can I solve this?我该如何解决这个问题?

try to use Expanded instead of Container in _buildImageBoxes() function尝试在 _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"),
        )
      ],
    );
  }

Expanded → Calculated Space Expanded →计算空间

Expanded or Flexible widgets in Column or Row will make Flutter calculate remaining space & use that space for layout. ColumnRow ExpandedFlexible小部件将使 Flutter 计算剩余空间并将该空间用于布局。

Widgets not in Expanded or Flexible are laid out regardless of screen/constraint space .不在ExpandedFlexible中的小部件的布局与屏幕/约束空间无关


Why / How this works为什么/这是如何工作的

Column and Row are laid out in two main phases: ColumnRow分为两个主要阶段:

  1. non- Flexible itemsFlexible物品
  2. Flexible items ( Expanded and Flexible widgets) Flexible项目( ExpandedFlexible小部件)

Phase 1阶段1

Flutter does Phase 1 without screen size or any other constraint in mind. Flutter 执行阶段 1 时没有考虑屏幕尺寸或任何其他限制。

Flutter just adds all non-flex-factor item sizes together. Flutter 只是将所有非 flex-factor 项目大小加在一起。

Sum too big for screen or other constraint?屏幕或其他限制的总和太大? RenderFlex overflowed exception. RenderFlex overflowed异常。

Phase 2阶段2

Widgets with flex constructor argument are flex-factor items.带有flex构造函数参数的小部件是 flex-factor 项目。

ie Flexible or Expanded widgets.FlexibleExpanded小部件。 ( Spacer too, but no one uses it.) (也有Spacer ,但没有人使用它。)

After Phase 1, any flex-factor widgets are laid out with remaining space in mind .在第 1 阶段之后,任何 flex-factor 小部件的布局都考虑到了剩余空间


Key difference between non-flexible and flex-factor layout phases:非灵活和弹性因子布局阶段之间的主要区别

  • non-flex layout → regardless of space非弹性布局 →不分空间
  • flex-factor layout → uses remaining space flex-factor 布局 → 使用剩余空间

Inside Column or Row , wrapping widgets in Expanded or Flexible , Flutter will calculate remaining space for their layout.ColumnRow ,将小部件包装在ExpandedFlexible ,Flutter 将计算其布局的剩余空间。 This would prevent a RenderFlex overflowed exception in the question since each Image widget will size itself to space constraints .这将防止问题中的RenderFlex overflowed异常,因为每个Image小部件都会根据空间限制调整自身大小

But during Phase 1, there are no space constraints .但在第一阶段,没有空间限制 So the Images aren't resized (and overflow).所以Images没有调整大小(和溢出)。

Children widgets inside Column or Row not wrapped in Expanded or Flexible will be laid out at their intrinsic size, regardless of screen/constraint space. ColumnRow包含在ExpandedFlexible子小部件将以其固有大小进行布局,而不管屏幕/约束空间如何。

Before

Space 400
  Column
    Image 150
    Image 150
    Image 150

Sum non-flex Images: 450. Space available: 400 → Overflowed总和非弹性图像:450。可用空间:400 → Overflowed

Solution : use Phase 2 → use calculated space解决方案:使用阶段 2 → 使用计算空间

After

Wrapping Image in flex widget Expanded , height available is calculated then shared among Expanded (as constraints) and Image is resized to fit inside Expanded constraints:Image包装在 flex 小部件Expanded计算可用高度,然后在Expanded之间共享(作为约束),并调整Image大小以适应Expanded约束:

Space 400
  Column
    Expanded 133
      → Image ←
    Expanded 133
      → Image ←
    Expanded 133
      → Image ←

Sum flex Expandeds: 399. Space: 400 → OK Sum flex Expandeds: 399. Space: 400 → OK

Widget build(BuildContext context) {

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

    return Container(
      height: _screenSize.height * 0.2,);
}                                                                                     

MediaQuery.of(context) It worked for me to use! MediaQuery.of(context)它对我有用!

在你的Image.network方法中使用fit属性来减小你的图像的大小,因为它们更大并且从你的容器中溢出,或者你可以通过它们的heightwidth属性来放大你的Containers

Error (because of keyboard):错误(由于键盘):

You can also run into this error while using a TextField which launches on-screen keyboard, to solve it set您也可以在使用启动屏幕键盘的TextField时遇到此错误,以解决它设置

Scaffold(
  resizeToAvoidBottomInset: false, // <-- Set it to false.
  body: SingleChildScrollView(
    child: Column(
      children: [
        SizedBox(height: 600),
        TextField(),
      ],
    ),
  ),
)

Error (without keyboard):错误(没有键盘):

Use Expanded/Flexible for your children in Column/Row.在列/行中为您的孩子使用Expanded/Flexible

  • Using Expanded :使用Expanded

     Column( children: [ Expanded( flex: 1, child: Widget1(), ), Expanded( flex: 2, child: Widget2(), ) ], )
  • Using Flexible :使用Flexible

     Row( children: [ Flexible( flex: 1, child: Widget1(), ), Flexible( flex: 2, child: Widget2(), ) ], )
  • Giving a fixed height:给出一个固定的高度:

     Column( children: [ SizedBox( height: 200, child: Widget1(), ), Expanded( flex: 2, child: Widget2(), ) ], )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM