我有以下观点
struct A: View {
var content: AnyView
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
// Common Elements
content
// More Common Elements
}
}
}
}
当我从另一个视图调用此视图时
A(nextInnerView())
发生两件事。首先,随着content
元素的大小更改,ScrollView会为过渡设置动画效果。其次,如果向下滚动然后更改content
,则滚动位置不会重置。
答案 0 :(得分:1)
这里是可能解决方案的演示。使用Xcode 11.4 / iOS 13.4进行了测试
此行为的起源是在SwiftUI渲染优化中,它试图重新渲染仅更改的部分,因此,方法是根据源自采访更改的条件来识别视图A(将其标记为完全更改),或者可以仅通过UUID()
进行标识。
struct TestInnerViewReplacement: View {
@State private var counter = 0
var body: some View {
VStack {
Button("Next") { self.counter += 1 }
Divider()
A(content: nextInnerView())
.id(counter) // << here !!
}
}
private func nextInnerView() -> AnyView {
AnyView(Group {
if counter % 2 == 0 {
Text("Text Demo")
} else {
Image(systemName: "star")
.resizable()
.frame(width: 100, height: 100)
}
})
}
}
struct A: View {
var content: AnyView
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
ForEach(0..<5) { _ in // upper content demo
Rectangle().fill(Color.yellow)
.frame(height: 40)
.frame(maxWidth: .infinity)
.padding()
}
content
ForEach(0..<10) { _ in // lower content demo
Rectangle().fill(Color.blue)
.frame(height: 40)
.frame(maxWidth: .infinity)
.padding()
}
}
}
}
}