Flutter Deep Dive, Part 3: “RenderFlex children have non-zero flex…”
This article is part of a four-part series. You can find the others here:
- Part 1: “RenderFlex children…”, wading into the Baby Pool
- Part 2: Taking the Plunge
- Part 3: A Flex is not a flex
- Part 4: The Flex Layout Algorithm
So, are you ready to get back into it? Yeah, me neither… but here we go, anyway.
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
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.
Flex is the Widget that
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
You want to make sure to remember that when there is something wrong with your
Column, the error isn’t going to say anything about a
Column. In fact, it won’t even say anything about a
Enter the RenderFlex
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
Columns. It has the
Many Widget class names have counterparts in the Render layer, with “Render” in front of them.
What happens is when you use a
Column in the Widget layer, it gets rendered as a
RenderFlex in the Render layer.
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
Column you want. As we said before, you could just use a
Flex in the Widget layer instead of a
Column, but that would confuse people.
But the Render layer does use a
RenderFlex, and that’s why the error says
RenderFlex and not
Flexible and FlexFit
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
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.
The fit… My Wife Says It’s All About the Shoes
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
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
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
The Trouble with Expandeds…
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.
You can stalk the author on Twitter at https://twitter.com/scottstoll2017
The latest Tweets from Scott Flutter (@scottstoll2017). Editor: Flutter Community Medium -- Organizer: @FlutterComm and…twitter.com