Articles, podcasts and news about Swift development, by John Sundell.

Swift clip: SwiftUI stacks and spacers

Published on 19 Feb 2020

Let’s take a look at how SwiftUI’s various stacks and spacers can be used to achieve many kinds of flexible, adaptive layouts with very little code. While SwiftUI does include several more advanced layout APIs, stacks and spacers are a great starting point for most UIs.

Emerge

Emerge: Continuously monitor and reduce your app’s size. Emerge’s easy to use plugins for GitHub and fastlane will automatically scan your app’s binary and provide you with simple, actionable suggestions on how to make it smaller and, in turn, faster for your users to download. Set up a demo now!

Sample code

A simple SwiftUI view that renders a text at the center of its parent container:

struct ContentView: View {
    var body: some View {
        Text("SwiftUI")
    }
}

Adding another text, and wrapping those two subviews within a VStack to render them on top of each other along the Y-axis:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("SwiftUI")
            Text("Layout")
        }
    }
}

Pushing our two texts to the top of the screen using a Spacer:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("SwiftUI")
            Text("Layout")
            Spacer()
        }
    }
}

Moving our texts to the top-left corner (or technically, top-leading corner), using an HStack and another Spacer:

struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
        }
    }
}

Adding padding to our view using the .padding() modifier:

struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
        }.padding()
    }
}

Adding an image rendered at the top-right (trailing) corner of the screen:

struct ContentView: View {
    var body: some View {
        HStack(alignment: .top) {
            VStack {
                Text("SwiftUI")
                Text("Layout")
                Spacer()
            }
            Spacer()
            Image(systemName: "star")
        }.padding()
    }
}

Extracting our current views into a new View type:

struct TopView: View {
    var body: some View {
        HStack(alignment: .top) {
            VStack {
                Text("SwiftUI")
                Text("Layout")
            }
            Spacer()
            Image(systemName: "star")
        }
    }
}

Using composition to form our content view, rather than having it contain all of our layout code:

struct ContentView: View {
    var body: some View {
        VStack {
            TopView()
            Spacer()
        }.padding()
    }
}

Adding a new layer to our view hierarchy using a ZStack:

struct ContentView: View {
    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            VStack {
                TopView()
                Spacer()
            }
            Text("A new layer")
        }.padding()
    }
}