2

我找到了一种使用 a和 a保存 ScrollViews偏移量的方法。GeometryReaderPreferenceKey

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

onAppear我想设置scrollTarget为保存位置的视图中。但它会滚动到任何地方,但不会滚动到我想要的位置。

我想过将偏移量除以一个项目的大小,但这真的是要走的路吗?听起来不太好。

4

1 回答 1

2

在这种情况下,您实际上不需要偏移量,只需存储当前可见视图的 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)
                        }
                    }
                }
            }
        }
    }
}
于 2021-01-24T14:10:47.420 回答