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

Mof*_*waw 12 scrollview ios swift swiftui

我需要找出我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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Asp*_*eri 17

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

使用 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)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在 Xcode 13 和 iOS 15 中,打印语句永远不会为我触发 (2认同)
  • 我遇到了 onReceive 未被调用的问题(在类似的代码中)。(删除 debounce() 调用避免了它——但这当然不是一个选项。)我最终通过使用 ` detector` 和 `publisher` @State 变量而不是 let-properties 来修复它。 (2认同)