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

Posted

技术标签:

【中文标题】如何检测 SwiftUI List 中的向上、向下、顶部和底部滚动【英文标题】:How to detect scroll up, scroll down, top and bottom in SwiftUI List 【发布时间】:2020-11-26 19:34:46 【问题描述】:

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

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

                    .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 添加到List 的? 【参考方案1】:

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

如果您不介意使用 Introspect,可以按照以下答案中的说明进行操作:https://***.com/a/65467199/3393964


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

【讨论】:

以上是关于如何检测 SwiftUI List 中的向上、向下、顶部和底部滚动的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的底部优先滚动

SwiftUI List - 禁用特定行的移动?

SwiftUI:滚动视图中的顶部锚定可调整大小视图

在 ScrollView 中阻止向下滚动 - SwiftUI

在 ListView 中检测向上滚动和向下滚动

检测用户的意图是点击还是在触觉设备上向上/向下滚动页面