我希望在ScrollView之外使用VStack,这样如果VStack扩展到屏幕大小之外,内容就可以滚动。现在,我想在GeometryReader中使用VStack,它会导致问题,我只能通过设置GeometryReader框架来解决问题,这并不能真正帮助我,因为我使用读取器来定义视图大小。
下面是没有ScrollView的代码,它运行得很好:
struct MyExampleView: View {
var body: some View {
VStack {
Text("Top Label")
.background(Color.red)
GeometryReader { reader in
Text("Custom Sized Label")
.frame(width: reader.size.width, height: reader.size.width * 0.5)
.background(Color.green)
}
Text("Bottom Label")
.background(Color.blue)
}
.background(Color.yellow)
}
}这将产生以下图像:

自定义大小的标签应该是全宽度,但高度应该是宽度的一半。现在,如果我将相同的代码包装在ScrollView中,就会发生这样的情况:

不仅仅是所有的东西都变小了,而且定制标签的高度也被忽略了。如果我设置了GeometryReader的高度,我可以调整它的行为,但是我希望GeometryReader能够和它的内容一样大。我怎样才能做到这一点?
谢谢
发布于 2020-10-10 13:02:44
应该理解,GeometryReader不是一个神奇的工具,它只是读取当前上下文父级中的可用空间,但是.ScrollView没有自己的可用空间,它是零,因为它从内部内容确定需要的空间.因此,在这里使用GeometryReader,您有循环子请求父母的大小,但父母期望大小从子.SwiftUI渲染器以某种方式解决了这个问题(找到最小的已知大小),只是为了不崩溃。
以下是您的场景的可能解决方案--这里的适当工具是视图首选项。用Xcode 12 / iOS 14编写和测试。

struct DemoLayout_Previews: PreviewProvider {
static var previews: some View {
Group {
MyExampleView()
ScrollView { MyExampleView() }
}
}
}
struct MyExampleView: View {
@State private var height = CGFloat.zero
var body: some View {
VStack {
Text("Top Label")
.background(Color.red)
Text("Custom Sized Label")
.frame(maxWidth: .infinity)
.background(GeometryReader {
// store half of current width (which is screen-wide)
// in preference
Color.clear
.preference(key: ViewHeightKey.self,
value: $0.frame(in: .local).size.width / 2.0)
})
.onPreferenceChange(ViewHeightKey.self) {
// read value from preference in state
self.height = $0
}
.frame(height: height) // apply from stored state
.background(Color.green)
Text("Bottom Label")
.background(Color.blue)
}
.background(Color.yellow)
}
}
struct ViewHeightKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}注:.如果您不确定视图所在的上下文,请不要使用GeometryReader。
https://stackoverflow.com/questions/64293429
复制相似问题