Flutter Deep Dive, Part 3: “RenderFlex children have non-zero flex…”

Scott Stoll
Mar 20, 2019 · 5 min read
Deep Dive Part 3, by Scott Stoll. Twitter: @scottstoll2017

This article is part of a four-part series. You can find the others here:

So, are you ready to get back into it? Yeah, me neither… but here we go, anyway.

A Flex is flexible in that it can adjust its size based on its children. But don’t confuse the fact that it can be flexible with an actual Flexible because that’s a different Widget and you’ll have problems if you get them confused.

So don’t confuse the Flex and the Flexible, or the fact that a Flexible has a flex(which is not the same thing as a Flex), and we want to remember that how the flex gets applied depends on the FlexFit.

Hot Tip: A Flex can have any number of Flexibles but a Flexible can only have one flex. And remember, a Flex is not a flex. Got that?

Okay, I’ll be nice. No more jokes for a little while.

The Flex is the Widget that Row and Column extend. They’re the only two Widgets in Flutter that extend Flex (as of Flutter 1.0). You could just use a Flex directly instead of Row/Column and set the AxisDirection property to up, down, left or right; but that would probably confuse people so maybe you should just stick to using Row/Column.

You want to make sure to remember that when there is something wrong with your Row or Column, the error isn’t going to say anything about a Row or Column. In fact, it won’t even say anything about a Flex.

Remember we talked about the three layers of a Flutter cake? The Widget, Element and Render layers? You need to understand the basic concept of those layers in order to understand why the error says “RenderFlex children…”. It’s because the error isn’t occurring in the Widget layer, it’s occurring in the Render layer, and the Render layer doesn’t have Rows or Columns. It has theRenderFlex.

Many Widget class names have counterparts in the Render layer, with “Render” in front of them.

What happens is when you use a Row or Column in the Widget layer, it gets rendered as a RenderFlex in the Render layer.

Remember, a Row or Column is just a Flex with certain values already hard coded. So, the Render layer just uses a RenderFlex, then sets the parameters to whatever is needed to make the Row or Column you want. As we said before, you could just use a Flex in the Widget layer instead of a Row or Column, but that would confuse people.

But the Render layer does use a RenderFlex, and that’s why the error says RenderFlex and not RenderRow or RenderColumn.

Flexible and FlexFit are a matched set. There’s a subclass of Flexible you’re probably already familiar with, the Expanded. We’ll dig into that in a moment but for now, let’s take a look at Flexibles and their fits.

The idea of a Flexible is it gives you a way to resize a Widget. It can make its child larger or smaller and it can be a great way to resize an image, among other things.

Quick Image Resizing Tip:

If the child of a Flexible is too large to fit inside the Flexible’s parent, then the child will be resized so it does fit. This is important because it’s an easy way to deal with an Image that’s too large and causing an overflow error (the black and yellow bars). Just stuff the image into an Expanded and put that Expanded into a Row or Column. Voila! It will be automatically resized to fit in whatever space is available, at runtime, and without you needing to write a bunch of code to do it.

This might sound like a joke, but it isn’t. She really does say it’s all about the shoes.

But back to business…

The easiest way to quickly understand fit is if you imagine a balloon inside of a shoe box. The Flexible is the balloon and its parent Flex (Column/Row) is the box.

If you blow the balloon up as much as you can while it’s inside of the shoe box, how does the balloon fit in the shoe box? Tight or loose?

Now you understand fit. Yes, it’s really that simple.

FlexFit.tight isn’t just going to gently get bigger until it gently touches the edges. It’s going to push to see if it can get its parent to give it more room… and it will push hard (along the main axis) until the parent (Row/Column) starts enforcing some boundaries and says, “No more. That’s all you get.”

Here’s the funny thing. Our Flexible (usually an Expanded), is going to have a child. So, you might be wondering how the child’s size gets calculated into all of this.

Answer: It doesn’t.

You can set the height or width parameter of the child to 1.0 or 100000.0; if the size parameter is along the main axis then it doesn’t matter because it’s going to be ignored. This is because a Flexible with FlexFit.tight (AKA an Expanded) is only concerned about what limitations its parent is placing on its size, not what its child wants.

That takes care of FlexFit.tight, but what about FlexFit.loose?

Take a look at this constructor:

Look at the third parameter of the call to super(). The fit has been hardcoded to FlexFit.tight, and you can’t change it. When you start getting RenderFlex errors involving an Expanded, that’s usually half the problem. This is what the error is talking about when it says “RenderFlex children have non-zero flex”.

The next thing to understand is how the layout algorithm handles multiple children within a single parent. This is how laying out the children of a Flex is handled.

Next up, Part 4: The Dreaded Flex Layout Algorithm…

You can stalk the author on Twitter at https://twitter.com/scottstoll2017

Flutter Community

Articles and Stories from the Flutter Community

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store