SwiftUI Series 02|Introduction to SwiftUI layout system: VStack, HStack, ZStack, Spacer and frame
What is really difficult is to understand the basic relationship between "parent constraints, child size, and container rearrangement" in SwiftUI layout.
When I first learned this piece of content, it was easiest to fall into a state when designing SwiftUI layout:
VStackI canHStackI will tooSpacerseems to understandframealso writes often
But as the page becomes more complex, these familiar problems begin to appear:
- This view is not full
- Added
framebut still not aligned SpacerAs soon as it is placed, it will crowd out other things.- After several levels of nesting, the page “can’t say what’s wrong, but it doesn’t look right”
This shows that many times we don’t really understand what SwiftUI layout is doing.
1. The most important thing about SwiftUI layout is the size negotiation process
If you only understand layout as “which Stack to use to place elements”, you will get stuck soon. Because the real core of SwiftUI layout is a size negotiation process, which can be roughly understood as:
- The superview gives an available space or proposed size
- The subview decides how big it wants to be based on this proposal
- The parent container then arranges the layout according to the size returned by the subview.
In other words, the layout is a constant negotiation between father and son.
Once this premise is understood, many seemingly metaphysical questions become clear:
- Some
frameare just covered with a shell TextandSpacerbehave very differently when put together- Some alignment issues are essentially offset during the size proposal stage.
2. VStack, HStack, ZStack The real difference is “who is leading which placement logic”
On the surface:
VStackVertically arrangedHStackarranged horizontallyZStackstacked rows
This is certainly true, but if you only remember this, you will still be confused when encountering complex layouts.
A more practical understanding is:
VStackmainly organizes sub-elements verticallyHStackmainly organizes sub-elements horizontallyZStackmainly stacks multiple elements in the same area
The key point is to think clearly:
- What is the core axis of the current page?
- Which layer is responsible for the main layout -Which layer is only local alignment and decoration
Many layouts are written in a messy manner, and the primary and secondary levels are not clearly distinguished.
3. The value of Spacer is “eating the remaining space”
When you use Spacer for the first time, you will intuitively understand it as “adding an empty box”.
This can lead to a lot of misuse.
More precisely, what Spacer does is:
Eat up as much remaining space as possible in the main axis direction of the current container.
For example, in HStack, it eats the horizontal space; in VStack, it eats the vertical space.
Once understood this way, it becomes easier to judge:
-Is it necessary to have a fixed spacing or to allocate remaining space?
- Should
paddingorSpacerbe used here? SpacerIf placed in the wrong position, the center of gravity of the entire layout will be shifted.
Many pages “look a little worse” because Spacer is used where fixed constraints should be used. As a result, the layout is quietly changed by the remaining space allocation logic.
4. frame is most easily misunderstood: it is not necessarily “modifying the content size”, in many cases it just wraps a layer of layout boxes
This is one of the easiest points for SwiftUI beginners to get stuck.
A common situation is to write:
Text("Hello")
.frame(maxWidth: .infinity)
Thought I was stretching Text.
To be more precise, in many cases, a larger layout area is provided outside the Text, rather than changing the internal content size of the Text itself.
This explains many common confusions:
- It looks wider, but the text is still not aligned to where I want it to be.
- Just use it with
alignment - The same
framehas different effects on different views
Therefore, the key to frame is not “changing the size”, but “what layout boundaries are added to the view”.
5. The real root cause of many layout problems is that the “main layout layer” and “local modification layer” are mixed together
Let’s take a very common anti-pattern:
- One outer layer
VStack - There are several layers inside
HStack - Add
frameto each layer - Mix some more
Spacer - Finally, rely on
paddingto repair it until you can see it.
This kind of writing method can certainly produce results in the short term, but once you change the length of the copy, the width of the screen, or the dynamic font, the layout will start to drift.
The root of the problem is often:
- Which layer is responsible for the main structure
- Which layer is responsible for local alignment -Which layer is just a visual modification?
There is no layering.
Once the layout loses its sense of hierarchy, it will become “relying on a bunch of modifiers to temporarily pull the position” instead of relying on the structure to be established naturally.
6. A more practical way of thinking about layout: first determine the main axis, then determine the remaining space, and then determine the local alignment
If I want to build a slightly more complex page today, I usually think in this order:
- Is this area dominated horizontally or vertically?
- Who should leave the remaining space to?
- Which places require fixed spacing and which places require flexible space.
- Which areas are only locally aligned and should not affect the global structure in turn.
This order can significantly reduce the situation of “more repairs and more chaos”. Because it forces you to decide the structure first and then decide the modification, instead of just relying on modifier to pile up the results.
7. Many SwiftUI pages “always look a little worse”
Many page problems are actually caused by insufficiently clear expression of structure.
Common manifestations include:
- The relationship between information blocks is not stable enough
- As long as the text is long, it will crowd out other things.
- The same card has strange proportions on different screens
Such questions are often:
- The space allocation logic is not clear
- The main layout axis and local modifications are mixed
- The fixed place is not fixed
- The flexibility has been written down again
Therefore, to truly learn layout is to learn to judge how space should be allocated.
8. Conclusion: What you really need to learn when getting started with SwiftUI layout is space negotiation rather than control names.
To put it in shorter form, I would say:
What you really need to master about SwiftUI layout is how the parent view proposes size, how the subview responds to the size, and how the container is placed based on these results.
Once this basic relationship is established, many layout issues will change from “metaphysical” to “reasonable”.
读完之后,下一步看什么
如果还想继续了解,可以从下面几个方向接着读。