How to Layer Views in SwiftUI Using ZStack

ZStack.gif

One of the first things I wondered when I started messing with SwiftUI was how am I supposed to build layered views? Every example I came across talked about horizontal stacks, vertical stacks, and lists. But what if I wanted to put text on top of another view? Then I found the answer…

ZStacks.

What’s a ZStack?

A ZStack is very similar to an HStack or a VStack, but instead of aligning along the X or Y axis it aligns things along the Z axis. The Z axis is basically the axis along which you can pile things up in your view. The lower the Z index of something, the further back towards the background it is.

ZStack in Practice

Let’s look at a simple example using a ZStack. Take a basic rounded rectangle to start:

RoundedRectangle(cornerRadius: 30)
    .foregroundColor(.blue)
    .frame(width: 200, height: 200)

When added to your view this will just create a blue rectangle with rounded corners. Now let’s add some text to it:

RoundedRectangle(cornerRadius: 30)
    .foregroundColor(.blue)
    .frame(width: 200, height: 200)
Text("ZStack")
    .foregroundColor(.white)
    .multilineTextAlignment(.center)

Aanndd we broke it! You can’t just add multiple Views in this way because SwiftUI has no way of knowing how they are supposed to be laid out. In order to have the text appear on top of the rectangle you’ll need to wrap the RoundedRectangle and the Text in a ZStack.

ZStack {
    RoundedRectangle(cornerRadius: 30)
        .foregroundColor(.blue)
        .frame(width: 200, height: 200)
    Text("ZStack")
        .foregroundColor(.white)
        .multilineTextAlignment(.center)
}

And just like that, the text is layered on top of the rectangle! Just keep in mind that ZStacks start at the back and work their way forward toward the screen. So if you were to swap the order of the Text and RoundedRectangle you would end up with Text that is hidden behind the rectangle.

Previous
Previous

Creating a Repeating Animation in SwiftUI

Next
Next

Responding to Keyboard Presentation/Dismissal in Swift