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

5

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

我尝试使用以下代码来检测滚动:

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

这个功能有时会出现间歇性问题,只有约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)
                        }
                    )

这会捕获我所有的滚动事件,非常棒。但是onEnded也会触发,问题在于我的列表并没有实际滚动。
我感到困惑,希望知道用户向上滚动、向下滚动的距离以及尽可能地了解用户何时到达列表的顶部。

你是如何给列表添加额外的 DragGesture 的? - Kai Zheng
1个回答

1

如果你想仅使用SwiftUI实现此操作,你可以在ScrollView中创建一个GeometryReader来检测偏移更改,如此处所示:https://fivestars.blog/swiftui/scrollview-offset.html

如果你不介意使用Introspect,你可以按照这个答案中的描述来实现:https://dev59.com/Grjna4cB1Zd3GeqP2wJZ#65467199


您可以使用 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
        }
        ...        
}


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

很不幸,您的答案仅适用于在UIKit中使用SwiftUI。但是,SwiftUI旨在用于watchOS、macOS等所有平台,因此任何答案都应该跨所有平台工作,而不仅仅是在UIKit上。 - CommaToast
@CommaToast ScrollViewProxy是跨平台的,有关如何在macOS上执行Introspect解决方案,请参阅GitHub。此外,几何读取器在所有平台上都可以使用。 - Casper Zandbergen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接