Understanding Flutter Constraints Rule 3 : Parent Sets Position
The position of a widget on the screen is determined by its parent. After receiving the size information from the widget, the parent sets the position one by one. This article explains that rule.
In the previous article, we learned about Flutter constraints rule 2: Sizes Go Up. This article focuses on the third and final rule: Parent sets position. So Let’s get started.
What Does “Parents Set Position” Mean?
Previously, we learned about how a widget defines its size. However, the widget itself does not know its position on the screen. It cannot answer where it will be positioned - at the bottom, top, or any other coordinates on the screen. The widget also does not know about the position of its sibling widgets.
The position of a widget on the screen is determined by its parent. After receiving the size information from the widget, the parent sets the widget's position based on the available space and constraints.
Note: In order to set the position of a child, the parent must first know the size of the child. Therefore, rule 3 is applied after rule 2 has been completed.
In the case of multiple widgets, such as a Row and a Column, the parent iterates through each child widget, gathers the size information, and then sets the position of each widget accordingly.
Let's consider the example of the Center widget from the first rule of this series.
In the above example, the Container does not know where it will be positioned or aligned on the screen. It's up to the ConstraintsBox to decide the Container's position.
The ConstraintsBox implementation is not designed to set its child's position. It is designed to set constraints on its child. So, in this case, the position of the ConstraintsBox will be the same as the position of the Container.
Now, what will be the position of the ConstraintsBox, and who will set its position?
The position will be set by its parent, the Center widget, and it will be set in the center of the screen.
How?
The Center widget is designed to set the position of its child, the ConstraintsBox, at the center based on the given constraints from its parent, i.e., MyApp.
For example, if the constraints passed to the Center are the size of (500, 700), then the Center will set the position of its child at (250, 350), which is the center point of the available space.
Also, MyApp is passing tight constraints to the Center widget, which forces the Center to take the full-screen size and set the position of the ConstraintsBox in the center of the screen.
What’s the position for MyApp?
Since MyApp is the root of the widget tree, the Flutter framework by default sets its position to the start of the screen i.e. (0, 0).
Additionally, if a child does not have any parentData, it will be set to the same position as its parent.
For example, if we set the Text "Hello" as a child of MyApp, then MyApp will set the position of the Text widget at (0, 0), or we can say it will be positioned in the same location as MyApp.
Tip: You can also use DevTools to check the position of a widget in the widget tree.
Devil Is in the Details
There are no set rules on how a parent widget will position its child. It entirely depends on the implementation and design of the parent widget.
For example:
The Row widget will position its children one after another in a horizontal line.
The Column widget will position its children one after another in a vertical line.
The Stack widget will position its children on top of each other based on their order.
The Center widget will position its child at the center of the total space available to the Center widget.
You can design your own custom widget to set positions differently.
If you're interested in delving deeper into how these calculations are done, I highly recommend watching this video.
Common Widget Position Problems and Solutions
Error: RenderFlex children have non-zero flex but incoming height constraints are unbounded
This error mostly occurs when we try to use an unbounded ListView inside a Column. We can fix this issue by wrapping each child in ListView with the Flexible or Expanded widget.
Filip Hráček has done a wonderful job explaining this exact error in the below video.
Conclusion
The widget tells its parent about its own size (within the original constraints, of course).
After getting the size from its children, the parent widget positions its children (horizontally on the x-axis, and vertically on the y-axis), one by one.
Due to this rule, we have some limitations on widgets:
A widget can’t know and doesn’t decide its own position on the screen, since it’s the widget’s parent who decides the position of the widget.
Since the parent’s size and position, in its turn, also depend on its own parent, it’s impossible to precisely define the size and position of any widget without taking into consideration the tree as a whole.
That's it for the third rule!
We've covered all three rules on Flutter constraints! If you have any questions, please let me know in the comments, and don't forget to subscribe to stay tuned for upcoming tips and tricks.
You can also follow me on Twitter for any updates.
Resources and Credits
From the official Flutter, doc check out Understanding constraints.