L3n*_*n95 4 ios swiftui geometryreader swiftui-scrollview
我找到了一种用 a和 a保存 ScrollViews偏移量的方法。GeometryReader
PreferenceKey
SwiftUI | 从 ScrollView 获取当前滚动位置
并且有一个滚动到设定位置ScrollViewReader
的方法。scrollTo
问题是,第一个方法保存偏移量,而第二个方法需要一个位置(或一个 id,与我的情况下的位置类似)。如何将偏移量转换为位置/id 或者是否有其他方法来保存和加载 ScrollViews 位置?
这是我现在拥有的代码,但它没有按照我想要的方式滚动:
ScrollView {
ScrollViewReader { scrollView in
LazyVGrid(columns: columns, spacing: 0) {
ForEach(childObjects, id: \.id) { obj in
CustomView(obj: obj).id(obj.id)
}
}
.onChange(of: scrollTarget) { target in
if let target = target {
scrollTarget = nil
scrollView.scrollTo(target, anchor: .center)
}
}
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) { // save $0 }
}
}.coordinateSpace(name: "scroll")
Run Code Online (Sandbox Code Playgroud)
在onAppear
视图中我想设置scrollTarget
为保存的位置。但它滚动到任何地方,但没有滚动到我想要的位置。
我考虑过将偏移量除以一个项目的大小,但这真的是正确的方法吗?听起来不太好。
Asp*_*eri 10
在这种情况下,您不需要实际偏移,只需存储当前可见视图的 id(您可以对如何检测它的数据使用任何适当的算法),然后滚动到具有该 id 的视图。
这是可能方法的简化演示。使用 Xcode 12.1/iOS 14.1 进行测试
struct TestScrollBackView: View {
@State private var stored: Int = 0
@State private var current: [Int] = []
var body: some View {
ScrollViewReader { proxy in
VStack {
HStack {
Button("Store") {
// hard code is just for demo !!!
stored = current.sorted()[1] // 1st is out of screen by LazyVStack
print("!! stored \(stored)")
}
Button("Restore") {
proxy.scrollTo(stored, anchor: .top)
print("[x] restored \(stored)")
}
}
Divider()
ScrollView {
LazyVStack {
ForEach(0..<1000, id: \.self) { obj in
Text("Item: \(obj)")
.onAppear {
print(">> added \(obj)")
current.append(obj)
}
.onDisappear {
current.removeAll { $0 == obj }
print("<< removed \(obj)")
}.id(obj)
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)