We have all seen it at one time or another. The dreaded “Viewport was given unbounded Height” error in Flutter. This line of text brings horror to the heart of almost all new Flutter developers. It seems cryptic. However, a little explanation goes a long way in understanding this error and how to fix it.
Before I go on, let me first say that everything I describe here for this error is also appropriate for the “Viewport given unbounded Width” message as well. The only difference is that you replace height with width. So let’s see how this error occurred.
Flutter was designed to draw it’s layout very fast! Speed was a major design goal for the framework. The developers came up with an ingenious set of data structures and algorithms to draw the layout blazingly fast. Flutter uses a single pass layout algorithm that walks down the widget tree, and then back up the tree. On the walk down the widget tree, each parent widget passes a set of constraints to it’s children. Basically asking the children “What size do you want to be?” The children then, reply on the walk back up the tree with “I want to be this size”. The parent then determines the location the child will be painted at, given the size it chose.
Column( children: <Widget>[ HeaderWidget(), ListView( // <<< Greedy widget children: <Widget>[...], ), ], )
Where this breaks down is with widgets like Row and Column. These widgets typically contain multiple children. In a typical column layout, the column asks the children for their desired size. The children then respond with I want to be “this” tall! The column then determines its own size and responds to its own parent.
This all works well until you place a widget like GridView or ListView in the column. The Column widget has an infinite height and the Row widget has an infinite width. Since a ListView also has an infinite height, it responds with “Please give me all the available height”. This causes an issue because the height is infinite!
You may ask why the Column doesn’t restrict its children to its own size. Well doing this would require multiple passes to compute the size of each child as any single child could respond with “I want it all!” leaving the other children-widgets with no space. The only response would be to lower the allowed space for the offending widget and then recompute the size for all children. This would solve the error issue but would greatly slow down the rendering of the layout, and the layout may end up displayed in ways you didn’t intend.
The Flutter developers chose to present an error warning you of the issue instead of trying to solve it for you at the cost of slowing performance and distorting your layout.
So how do we fix this error? Well, the short answer is to give greedy widgets a tight constraint. For example, given a Column widget containing multiple children with one child being a ListView, wrap the ListView in an Expanded or Flexible widget to allow it to be as large as possible while still giving space to the other children.
Column( children: <Widget>[ HeaderWidget(), Expanded( child: ListView( children: <Widget>[...], ), ), ], )
If you want your ListView to be a specific size, then wrap it with SizedBox. This will limit its size and allow the parent Column or Row to function properly.
Column( children: <Widget>[ HeaderWidget(), SizedBox( height: 50.0, child: ListView( children: <Widget>[...], ), ), ], )
I hope this explanation has helped you to understand the issue and how to solve it. Having a good understanding of how Flutter’s layout mechanism works can help you debug a lot of layout issues. You will often hear people say (me included) that constraints go down and geometry goes up. This is a reference to how each parent widget asks its child how big it wants to be. The constraint comes from the fact that the parents really say, “Children, I have this much height. How much of it do you want?”, and the children respond with “I want to be this size”. With the size now available to the parent widget, it can compute the locations for each child. But for widgets like the Column as a parent, the parent has an infinite height. When given a child that also has an infinite height, issues arise. Now you known how to fix them!
Until next time, Happy coding!