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

I am using GridView in my Flutter app to display images and their titles. 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

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

enter image description here

How can I solve this?


Solution 1:

try to use Expanded instead of Container in _buildImageBoxes() function

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

Solution 2:

Expanded → Calculated Space

Expanded or Flexible widgets in Column or Row will make Flutter calculate remaining space & use that space for layout.

Widgets not in Expanded or Flexible are laid out regardless of screen/constraint space.


Why / How this works

Column and Row are laid out in two main phases:

  1. non-Flexible items
  2. Flexible items (Expanded and Flexible widgets)

Phase 1

Flutter does Phase 1 without screen size or any other constraint in mind.

Flutter just adds all non-flex-factor item sizes together.

Sum too big for screen or other constraint? → RenderFlex overflowed exception.

Phase 2

Widgets with flex constructor argument are flex-factor items.

i.e. Flexible or Expanded widgets. (Spacer too, but no one uses it.)

After Phase 1, any flex-factor widgets are laid out with remaining space in mind.


Key difference between non-flexible and flex-factor layout phases:

  • non-flex layout → regardless of space
  • flex-factor layout → uses remaining space

Inside Column or Row, wrapping widgets in Expanded or Flexible, Flutter will calculate remaining space for their layout. This would prevent a RenderFlex overflowed exception in the question since each Image widget will size itself to space constraints.

But during Phase 1, there are no space constraints. So the Images aren't resized (and overflow).

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.

Before

Space 400
  Column
    Image 150
    Image 150
    Image 150

Sum non-flex Images: 450. Space available: 400 → Overflowed

Solution: use Phase 2 → use calculated space

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:

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

Sum flex Expandeds: 399. Space: 400 → OK