VStack bottom alignment in SwiftUI

Currently building a chat application and I need new messages to appear at the bottom of the screen. I also need to have messages aligned to the bottom. However, using VStack inside ScrollView features top alignment by default.

!

    ScrollView {
        VStack(alignment: .leading, spacing: 16) {
            Spacer()
            .frame(minWidth: 0, maxWidth: .infinity, minHeight:0, maxHeight: .infinity, alignment: Alignment.topLeading)
            ForEach(notList, id: \.self) { not in
                NotRow(not: not)

            }

        }
        .padding()
        .frame(minWidth: 0, maxWidth: .infinity, minHeight:0, alignment: Alignment.topLeading)

    }

What should I do to fix this?

Try changing all of your Alignment.topLeadings to Alignment.bottomLeading

The distance between adjacent subviews, or nil if you want the stack to choose a default distance for each pair of subviews.

I think you're missing a maxHeight in VStack

VStack(alignment: .leading) {
  Spacer().frame(maxWidth: .infinity)
  // content here
}
.frame(maxHeight: .infinity) // <- this

The chapter entitled SwiftUI Stacks and Frames touched on the basics of alignment in the context of stack container views. Inevitably, when it comes to designing complex user interface layouts, it will be necessary to move beyond the standard alignment options provided with SwiftUI stack views.

If you remove Spacer() and put it after the closing braces of your ForEach, it will fix it. Here is how your updated code will look like:

ScrollView {
        VStack(alignment: .leading, spacing: 16) {
            .frame(minWidth: 0, maxWidth: .infinity, minHeight:0, maxHeight: .infinity, alignment: Alignment.topLeading)
            ForEach(notList, id: \.self) { not in
                NotRow(not: not)

            }
            Spacer()
        }
        .padding()
        .frame(minWidth: 0, maxWidth: .infinity, minHeight:0, alignment: Alignment.topLeading)

    }

VStack { Text("SwiftUI") Divider() Text("rocks") } By default, items in your stacks are aligned centrally. In the case of HStack that means items are aligned to be vertically in the middle, so if you have two text views of different heights they would both be aligned to their vertical center.

VStack(alignment: .leading) { Text("Hello, world!") .alignmentGuide(.leading) { d in d[.trailing] } Text("This is a longer line of text") } And now you’ll see why I added colors: the first text view will move to the left so that its right edge sits directly above the left edge of the view below, the VStack will expand to contain it, and the

The alignment parameter in the container view (VStack, HStack or ZStack), has two effects: Determine which.alignmentGuides () are relevant for layout. All the alignment guides that have a different alignment than the one in the container parameter, will be ignored during layout.

I am experimenting with SwiftUI and just trying to have a button at the bottom. Right now it is centered. Wondering how I could force a view to stick superview's bottom as you would do in AutoLayout. struct ContentView : View { var body: some View { VStack { Text("Test") } } } Thank you!!!

Comments
  • And you want the empty space to be scrollable ?
  • I want it to behave like in chat apps: you can do little scrolling but messages return to the bottom.