【问题标题】:UICollectionView: how to detect when scrolling has stoppedUICollectionView:如何检测滚动何时停止
【发布时间】:2013-02-14 05:19:34
【问题描述】:

我正在使用UICollectionView 快速滚动浏览一组缩略图。滚动结束后,我想显示当前缩略图的更大高分辨率版本。

如何检测用户何时完成滚动?我确实实现了didEndDisplayingCell,但这只会告诉我某个特定单元格何时滚动;它没有告诉我滚动动作何时真正完成。

【问题讨论】:

    标签: ios objective-c ios6 uicollectionview


    【解决方案1】:
    NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView
    

    UICollectionViewUIScrollView 的子类。因此,如果您设置了委托并实现了UIScrollViewDelegate,您应该能够以与UIScrollView 相同的方式检测到这一点。

    例如:-

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
    

    根据documentation,上述方法应该告诉滚动视图何时结束,从而使滚动运动减速。

    【讨论】:

    • 太棒了。你不知道这救了我多少讨厌的代码。我试图在我的 UICollectionViewFlowLayout 中使用 shouldInvalidateLayoutForBoundsChange 回调来监控它。多么n00b。
    • 请参阅 D6mi 下面关于 scrollViewDidEndScrollingAnimation 的说明。程序化滚动不会调用 scrollViewDidEndDecelerating。
    • 确实,我不明白为什么当前的答案是公认的,它不起作用 scrollViewDidEndDecelerating 没有被调用,但就像 D6mi 所说,scrollViewDidEndScrollingAnimation 被调用
    • 这个答案不完整。
    • 出色的答案。 @Nathanael,答案是完整的,因为他指出 UICollectionView 是 UIScrollView 的子类,并且还引用了一个 eg:- 委托方法。其余的答案只是采用了这个答案并向其中添加了其他委托方法。理想情况下,休息应该只是对这个答案的评论。关键是collectionview只是一个scrollview,剩下的可以搞定。
    【解决方案2】:

    只是为了覆盖你的基础,你应该实现这两个 UIScrollViewDelegate 方法。 在某些情况下,可能没有减速(并且不会调用scrollViewDidEndDecelerating),例如,页面完全滚动到位。在这种情况下,请在scrollViewDidEndDragging 中进行更新。

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {
      if (!decelerate) {
        [self updateStuff];
      }
    }
    
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
      [self updateStuff];
    }
    

    【讨论】:

    • 感谢您分享这个!这应该是接受的答案 b/c OP 询问“滚动已停止”——如果没有两种方法,用户可以轻松地向下滚动集合视图并释放手指而无需轻弹,scrollViewDidEndDecelerating 不会被调用,scrollViewDidEndDragging 会.感谢您发布此答案。
    【解决方案3】:

    这里需要注意一个重要的事实。

    在用户启动的滚动(即平移手势)上调用此方法:

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

    或在 Swift 中:

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)


    另一方面,在所有手动(以编程方式)启动的滚动(如 scrollRectToVisiblescrollToItemAtIndexPath)上都会调用这个:

    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView

    或在 Swift 中:

    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView)

    【讨论】:

      【解决方案4】:

      Swift 3 版本的 Abey M 和 D6mi 的答案:

      当滚动是由用户操作引起的时

      public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
          if (!decelerate) {
              //cause by user
              print("SCROLL scrollViewDidEndDragging")
          }
      }
      
      public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
          //caused by user
          print("SCROLL scrollViewDidEndDecelerating")
      }
      

      当滚动是由代码操作(以编程方式)引起时:(如“scrollRectToVisible”或“scrollToItemAtIndexPath”)

      public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
          //caused by code
          print("SCROLL scrollViewDidEndScrollingAnimation")
      }
      

      注意事项:

      • 将这些函数放入您的 UIScrollViewDelegate 或 UICollectionViewDelegate 委托中。
      • 如果您没有单独的委托,请将当前类扩展为类文件顶部的 UIScrollViewDelegate 操作

      .

      open class MyClass: NSObject , UICollectionViewDelegate
      

      在你的 viewWillAppear 的某个地方,让这个类成为它自己的代表

      override open func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          // ...
          self.myScrollView.delegate = self
          // ...
      }
      

      【讨论】:

        【解决方案5】:

        Swift 3 版本:

        func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
            // Your code here
        }
        

        【讨论】:

          【解决方案6】:

          如果你想使用可见的索引路径:

          - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
          {
              [self scrollingFinish];
          }
          - (void)scrollingFinish {
          
          
              if([self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader]){
                  NSIndexPath *firstVisibleIndexPath = [[self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader] firstObject];
                  [self.collectionView scrollToItemAtIndexPath:firstVisibleIndexPath atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
                  [NSObject cancelPreviousPerformRequestsWithTarget:self];
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2012-01-01
            • 1970-01-01
            • 2015-10-22
            • 2012-02-27
            • 2021-05-09
            • 2014-08-20
            • 1970-01-01
            • 2011-03-31
            • 1970-01-01
            相关资源
            最近更新 更多