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