"RenderStack object was given an infinite size during layout" when using Positioned inside a Stack

3.6k views Asked by At

I'm creating a widget that presents a Stack inside a Container. Inside the Stack there is a dynamic Column inside a Positioned widget, which sticks the Column to the Bottom.

I am trying to wrap the Stack in a SingleChildScrollView, that if the dynamic Column will have lots of children it will be able to scroll.

But after I add the scroll view I get this error message:

RenderStack object was given an infinite size during layout.

2

There are 2 answers

9
RegularGuy On BEST ANSWER

A scrollView doesn't have height, it will use infinite height for it's children. So the stack should be wrapped in a sizedBox widh a known height in case that you want that. If you want the stack to fill the screen then remove the singleChildScrollview completely. And if you want the stack to be scrollable from the inside. Just add SingleChildScrollView inside the stack

return Scaffold(
      body: Container(
        color: Colors.blue[100],
        child: Stack(
          children: [
            Positioned.fill(child: SingleChildScrollView(child: MyColumn()))
          ],
        ),
      ),
    );

EDIT 1: Ok the problem is the layout itself. Since you only use the stack to position the image. And you know the widht and height of the image, and the background shape fills all the items. We could

Isolate the stack only to the image, and use padding and some calculation to have the layout build in a similar way.

Then render everything else inside a normal column

My implementation https://dartpad.dev/230b14d8f0b22b45929a75c208786257

6
Nitrodon On

From the RenderStack documentation:

First, the non-positioned children (those with null values for top, right, bottom, and left) are laid out and initially placed in the upper-left corner of the stack. The stack is then sized to enclose all of the non-positioned children. If there are no non-positioned children, the stack becomes as large as possible.

Since all of your Stack's children are positioned, Stack will match the maximum size constraint passed down by the SingleChildScrollView. This size has infinite height, so the Stack is forced to have infinite height as well.

To fix this, you will need to find another way to accomplish what you want. One option that comes to mind involves a ConstrainedBox providing a minimum height (obtained from a LayoutBuilder), a non-positioned Column, and a bottomCenter alignment on the Stack itself. This is similar to the first code sample in the SingleChildScrollView documentation:

LayoutBuilder(
  builder: (context, constraints) {
    return SingleChildScrollView(
      child: ConstrainedBox(
        // This ensures that the Stack fills the entire viewport,
        // even if the Column is small.
        constraints: BoxConstraints(
          minHeight: constraints.maxHeight,
        ),
        child: Stack(
          // Place the only non-positioned child (the column) at the bottom
          alignment: Alignment.bottomCenter,
          children: [
            Column(
              mainAxisSize: MainAxisSize.min,
              children: [ /* ... */ ]
            )
          ]
        )
      )
    );
  }
)