如何检测 SwiftUI 列表中的向上滚动、向下滚动、顶部和底部

Pau*_*ulG 5 swiftui swiftui-list

我有一个列表,我想在列表向上滚动时隐藏工具栏和选项卡栏。

我尝试使用以下方法来检测运动:

                    .gesture(
                        DragGesture()
                        .onChanged { value in
                            if value.translation.height > 0 {
                                print("Scroll down")
                            } else {
                                print("Scroll up")
                            }
                        }
                        .onEnded{ value in
                            print("ended")
                        }
                    )

Run Code Online (Sandbox Code Playgroud)

这会间歇性地工作,因为只有大约 80% 的时间,它似乎只有在我缓慢地滚动或者当我将手指直接放在屏幕上然后滚动时才能检测到滚动。否则什么也没有。而且,onEnded这里从来不开火。

我也尝试过这个:

                    .gesture(
                        DragGesture(minimumDistance: 0, coordinateSpace: .local)
                        .onChanged { value in
                        
                            print(value.translation.height)

                            if value.translation.height > 0 {
                                print("Scroll down")
                            } else {
                                print("Scroll up")
                            }
                        }
                        .onEnded{ value in
                            print("ended")
                            
                            print(value.location.y)
                        }
                    )
Run Code Online (Sandbox Code Playgroud)

这能捕捉到我所有的滚动,这太棒了。onEnded也会触发,但问题是我的列表实际上并没有滚动。

我在这里不知所措,我想知道用户何时向上滚动、向下滚动、滚动多少,如果可能的话,我想知道用户何时到达列表顶部。

Cas*_*gen 1

如果您只想在 SwiftUI 中执行此操作,则可以在 ScrollView 内创建一个 GeometryReader 来检测偏移量变化,如下所示: https: // Fivestars.blog/swiftui/scrollview-offset.html

如果您不介意使用内省,您可以按照此答案中的描述进行操作:/sf/answers/4582703961/


您可以使用Introspect获取 UIScrollView,然后从中获取 UIScrollView.contentOffset 和 UIScrollView.isDragging 的发布者,以获取可用于操作 SwiftUI 视图的这些值的更新。


struct Example: View {
    @State var isDraggingPublisher = Just(false).eraseToAnyPublisher()
    @State var offsetPublisher = Just(.zero).eraseToAnyPublisher()

    var body: some View {
        ...
        .introspectScrollView {
            self.isDraggingPublisher = $0.publisher(for: \.isDragging).eraseToAnyPublisher()
            self.offsetPublisher = $0.publisher(for: \.contentOffset).eraseToAnyPublisher()
        }
        .onReceive(isDraggingPublisher) { 
            // do something with isDragging change
        }
        .onReceive(offsetPublisher) { 
            // do something with offset change
        }
        ...        
}

Run Code Online (Sandbox Code Playgroud)

如果你想看一个例子;我使用此方法来获取我的包ScrollViewProxy中的偏移量发布者。