SwiftUI: Layout & Interfaces

Nov 18 2021 Swift 5.5, iOS 15, Xcode 13

Part 2: Aligning Views

10. Stack Alignment

Episode complete

Play next episode

Next
Save for later
About this episode
See versions

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 9. Introduction Next episode: 11. Challenge: Align Nested Stacks

This course was originally recorded in 2019. It has been reviewed and all content and materials updated as of October 2021.

If you’ve gone through our iOS and Swift for Beginners Learning Path up to this point, you’ll have gotten somewhat familiar with Stacks, already.

As a refresher, a stack is a container view that arranges its children in a line. You use HStacks for horizontal lines, and VStacks for vertical ones.

They’re the bread and …peanut butter of SwiftUI layout. In this episode, you’ll learn about the jelly: Alignment! I say that because… it makes all the views inside the stack …jell …together. You’ll see!

Let’s start off with a VStack. Make sure you’ve got the canvas showing…

…if it’s not, you can bring it around with option-command-return. And the keyboard shortcut for refreshing your Previews is option-command-P. As long as the canvas is open, you can command-click on the Text view, in code or in the canvas, and embed it in a VStack.

    VStack {
      Text("Hello, World!")
    }

Then, add a couple of images to the top of the stack. To get at the images I’ve included for you, you can open the Library with Shift-Command-L and click the Media Tab icon. Put the Cake at the top of the stack.

So, that’s huge. Let’s make it resizable…

    VStack {
      Image("Cake VStack")
        .resizable()
      Text("Hello, Layout!")

…and scale it to fit.

        .resizable()
        .scaledToFit()
      Text("Hello, Layout!")

Copy those three lines of Image code with command-C and paste them below the text using option-shift-command-V to preserve the modifier indentation.

      Text("Hello, Layout!")
      Image("Cake VStack")
        .resizable()
        .scaledToFit()
    }

Then, change that bottom image to “Pancake VStack”. For variety.

Image("Pancake VStack")

At the moment, we’re not passing any arguments to the VStack initializer other than its content, but there are two other possibilities. Which we’ll explore, using the inspector for the VStack. If you option-control click in the area to the left or right of the Text view, you can access it. As soon as you adjust this first option, “Spacing”…

…you’ll see the spacing VStack initializer argument appear in your code.

If you make it big enough…

…the image views will shrink, as the stack gets spaced out.

And if you make spacing negative enough…

…you can get views to overlap.

But we’re going to be focusing on another property, so just get rid of the spacing.

VStack {

Then, option-control-click on the pancake Image, and give it a frame of 100 by 100. Also, delete “Scaled To Fit” because you won’t need it, with the image being smaller.

Now, open the inspector for the VStack, by option-control-clicking to either side of the text or pancakes and click on the button next to Alignment. That inserts the alignment argument into your VStack’s initializer. And it repositions all but the largest view in your stack, so they’re lined up on the leading edge.

If you press the third button over, you’ll get “trailing” edge behavior instead. And if you pick the second button, your views will be centered. But center is the default, so you don’t need to specify it.

If you don’t use an explicit alignment argument, that’s when the the last button gets highlighted.

VStack {

Now, let’s switch the Stack’s axis by changing the “V” to an “H”.

HStack {

To match VStacks, you’ve got buttons for the top edge…

…and the bottom edge. Press that too. And there’s center…

…but again, that’s the default.

A difference with HStacks is that there are other options that don’t appear as buttons. If you go to the alignment argument, and delete the existing value, after the dot, you can hit escape to get code completion options, and see what else is available: First Text Baseline, and Last Text Baseline. Start with “First Text Baseline”.

HStack(alignment: .firstTextBaseline) {

So now, the images are lined up with the text. But with a single line of text, “first” and “last” baseline are the same vertical value.

Let’s add a couple of “newline” characters to the Text, using backslash-n, and then we’ll be able to observe the difference.

Text("Hello, \nLayout\n!")

Now, the images are lined up with the bottom of “Hello”. And when you’re using a baseline alignment value, you’ll be able to use a dropdown in the Inspector, instead of buttons, where you can select “Last Text Baseline”. With that, the images move to where the exclamation point is.

That’s really all there is to the built-in alignment options for HStacks and VStacks. But as long as we’re focusing on text, you should also be aware that Text Views have VStack-like alignment capabilities.

You can access those by using the Inspector for a Text View.

You’ve got options for trailing , center, and leading. In code, these are all represented with the multilineTextAlignment modifier.

But like with VStacks, there’s a default: which is leading, instead of center. So you don’t need to manually specify leading alignment.

The key thing to remember about alignment is that it occurs perpendicularly to the primary axis of a Stack. If you’ve got an HStack, you’ll be using instances of the VerticalAlignment structure. And for a VStack, you’ll use HorizontalAlignment.

…which is actually a different structure than TextAlignment, even though they have have the same leading, center, and trailing options.

In our “Your First iOS and SwiftUI App” course, you learned how you can put Stacks of one axis inside a Stack of another axis. That’s called “nesting stacks”.

When you combine the power of nesting, with alignment, you can achieve a ton of different layout combinations! You’ll explore some of the possibilities in the upcoming challenge.