Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Spacer doesn't work at ScrollView

How can I get space in VStack to pin the button at the bottom?

ScrollView {
        VStack() {
            Text("Title_1")
                .padding(.bottom, 35.0)
            Text("Title_2")
                .padding(.bottom, 32.0)
            Text("Title_3")
                .padding(.bottom, 27.0)
            
            Spacer()
            Button(action: { print("ACTION") }) {
                Text("OK")
                    .font(.title)
                    .fontWeight(.semibold)
                    .foregroundColor(Color.red)
                    
            }
            .frame(height: 35)
            .cornerRadius(8.0)
            .padding(.bottom, 25.0)
        }
        .frame(maxWidth: .infinity)
    }

what I have

what I want to have

like image 829
Maxim Avatar asked Sep 05 '25 17:09

Maxim


2 Answers

The ScrollView gives that VStack infinite possible height. That's why the spacers not working.

The Fix:

  • Give the VStack a minimumHeight that’s the height of the ScrollView or View
  • Also important to set the scrollview's width to be the view's width
GeometryReader { geometry in
    ScrollView(showsIndicators: false) {
        VStack {
        ...
        }
        .frame(minHeight: geometry.size.height)
    }.frame(width: geometry.size.width)
}

THIS WAY THE CONTENT WILL BE ABLE TO LAYOUT BEYOND THE VIEW's HEIGHT IF NEEDED

like image 79
8HP8 Avatar answered Sep 08 '25 11:09

8HP8


Use GeometryReader

A container view that defines its content as a function of its own size and coordinate space. https://developer.apple.com/documentation/swiftui/geometryreader

GeometryReader { geometry in
    ScrollView {
        VStack() {
          -----
        }
        .frame(width: geometry.size.width, height: geometry.size.height)
    }
}

Doing so, the VStack is full-screen.


You may not neeed to use ScrollView, because you do not need to scroll to see its content.

    var body: some View {
        
        VStack() {
            Text("Title_1")
                .padding(.bottom, 35.0)
            Text("Title_2")
                .padding(.bottom, 32.0)
            Text("Title_3")
                .padding(.bottom, 27.0)
            
            Spacer()
            Button(action: { print("ACTION") }) {
                Text("OK")
                    .font(.title)
                    .fontWeight(.semibold)
                    .foregroundColor(Color.red)
                
            }
            .frame(height: 35)
            .cornerRadius(8.0)
            .padding(.bottom, 25.0)
        }
        .frame(maxWidth: .infinity)
    }

But if your content's height is more than the screen height, the OK button is at the bottom, regardless. Hence, you do not need to do anything.

like image 23
mahan Avatar answered Sep 08 '25 12:09

mahan