SwiftUI-检测ScrollView何时完成滚动?

我需要找出我ScrollView停止移动的确切时刻。SwiftUI 可以实现吗?

这将是UIScrollView.

想了很久还是不明白……

一个用于测试的示例项目:

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                ForEach(0...100, id: .self) { i in
                    Rectangle()
                        .frame(width: 200, height: 100)
                        .foregroundColor(.green)
                        .overlay(Text("(i)"))
                }
            }
            .frame(maxWidth: .infinity)
        }
    }
}

谢谢!

回答

这是可能的方法的演示 - 使用带有去抖动的已更改滚动内容坐标的发布者,因此仅在坐标停止更改后才报告事件。

使用 Xcode 12.1 / iOS 14.1 测试

注意:您可以使用 debounce period 来调整它以满足您的需要。

import Combine

struct ContentView: View {
    let detector: CurrentValueSubject<CGFloat, Never>
    let publisher: AnyPublisher<CGFloat, Never>

    init() {
        let detector = CurrentValueSubject<CGFloat, Never>(0)
        self.publisher = detector
            .debounce(for: .seconds(0.2), scheduler: DispatchQueue.main)
            .dropFirst()
            .eraseToAnyPublisher()
        self.detector = detector
    }
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                ForEach(0...100, id: .self) { i in
                    Rectangle()
                        .frame(width: 200, height: 100)
                        .foregroundColor(.green)
                        .overlay(Text("(i)"))
                }
            }
            .frame(maxWidth: .infinity)
            .background(GeometryReader {
                Color.clear.preference(key: ViewOffsetKey.self,
                    value: -$0.frame(in: .named("scroll")).origin.y)
            })
            .onPreferenceChange(ViewOffsetKey.self) { detector.send($0) }
        }.coordinateSpace(name: "scroll")
        .onReceive(publisher) {
            print("Stopped on: ($0)")
        }
    }
}


以上是SwiftUI-检测ScrollView何时完成滚动?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>