SwiftUI: ScrollView中的Spacer无效

19

我该如何在VStack中获得空间以将按钮固定在底部?

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)
    }

我拥有的

我想要拥有的

3个回答

32

ScrollView使得VStack具有无限可能的高度,这就是为什么间隔器不起作用的原因。

解决方法:

  • VStack一个minimumHeight,这个高度应该是ScrollViewView的高度
  • 同样重要的是将scrollviewwidth设置为viewwidth
GeometryReader { geometry in
    ScrollView(showsIndicators: false) {
        VStack {
        ...
        }
        .frame(minHeight: geometry.size.height)
    }.frame(width: geometry.size.width)
}

这样就可以让内容在需要时超出视图的高度进行布局


一眼看上去,这个看起来很不错并且能够工作。但遗憾的是,至少在iOS 15中,由于这种方法,VStack内部的文本视图可能会被压缩,导致文本被截断。测试方法:将几个文本视图块放入Stack中,使其成为一个屏幕高度的内容,我的情况下,其中一些文本视图会被压缩,而另一些则不会。 - NeverwinterMoon
@NeverwinterMoon,我刚刚检查过了,现在对我来说是有效的,也许这是一个被修复的错误。 - passatgt
很遗憾,如果它在NavigationView内部,这会有一些奇怪的行为。 - joshuakcockrell

13

使用 GeometryReader

一个容器视图,它将自己的大小和坐标空间定义为其内容的函数。 https://developer.apple.com/documentation/swiftui/geometryreader

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

这样做,VStack是全屏的。


你可能不需要使用ScrollView,因为你不需要滚动来查看其内容。

    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)
    }

但如果您的内容高度超过屏幕高度,那么“确定”按钮将始终位于底部。因此,您无需进行任何操作。


-2

像其他答案建议的将minHeight设置为屏幕高度是可行的,但会带来一个问题,即ScrollView将不再滚动超出屏幕高度。

适当的解决方法是在ScrollView外面包裹一个VStack。

对于您的情况,

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

它不会给你最好的用户体验。 - Hamad Fuad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接