iosswiftswiftuispacing

Align item .trailing without stretching container in SwiftUI


I have a button which is nested in some other components. I want the button to be aligned to the right (trailing), even though the rest of the VStack items are leading.

When I use a Spacer() in an HStack, it stretches the HStack, and its parent container, to the width of the screen. I do not want to change the width of the parent, I just want to right align the button within the existing sized container.

Replicated below:

var body: some View {
    VStack(alignment: .leading, spacing: 0) {
        Spacer()
        VStack {
            VStack(alignment: .leading) {
                Text("Long text to stretch container a bit")
                    .font(.body)
                    .padding(.bottom)
                Text("But not stretch too much")
                    .font(.caption2)
                    .opacity(0.8)
                HStack() {
//                       Spacer()
                    Button(action: {print("Hello")}) {
                        Text( "\(Image(systemName: "chevron.right"))")
                    }
                    .buttonStyle(.borderedProminent)
                }
            }
            
        }
        .padding()
        .background(Color.accentColor)
        .cornerRadius(15)
    }
}

Solution

  • As you've found, Spacer() takes as much space as it can, growing your container. You can prevent this by adding .fixedSize() to the VStack, which means it will be fixed at its "ideal" size, instead of the "maximum" size that the spacer is aiming for:

    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            Spacer()
            VStack {
                VStack(alignment: .leading) {
                    Text("Long text to stretch container a bit")
                        .font(.body)
                        .padding(.bottom)
                    Text("But not stretch too much")
                        .font(.caption2)
                        .opacity(0.8)
                    HStack() {
                        Spacer()
                        Button(action: {print("Hello")}) {
                            Text( "\(Image(systemName: "chevron.right"))")
                        }
                        .buttonStyle(.borderedProminent)
                    }
                }
            }
            .padding()
            .background(Color.accentColor)
            .cornerRadius(15)
            .fixedSize()
        }
    }