【问题标题】:Scroll UICollectionView at a given speed using UIPanGestureRecognizer使用 UIPanGestureRecognizer 以给定的速度滚动 UICollectionView
【发布时间】:2020-02-16 03:49:44
【问题描述】:

我正在尝试实现与库存 iOS 照片应用类似的照片选择方法。这可以使用UIPanGestureRecognizer 来禁用UICollectionView 上的滚动。在 stock photos 应用程序中,似乎当平移到达屏幕顶部或底部时,滚动视图开始以给定速度滚动,并且越靠近屏幕边缘,滚动越快。

在UIScrollView 或UICollectionView 中似乎没有以给定速度滚动的 API。有没有什么聪明的方法可以用现有的方法来做到这一点,比如scrollToVisibleRect,或者在动画块中设置内容偏移量?我担心虽然这些方法可能有效,但它们的动作会很生涩!

【问题讨论】:

    标签: ios scroll uicollectionview uiscrollview


    【解决方案1】:

    我最终为此创建了一个 SpeedScrollableCollectionViewController 并使用 UIPanGestureRecognizer 控制它(与问题无关

    class SpeedScrollableCollectionViewController: UICollectionViewController {
    
        private var lastFrameTime: CFTimeInterval?
        
        private var displayLink: CADisplayLink?
       
        override init(collectionViewLayout layout: UICollectionViewLayout) {
            super.init(collectionViewLayout: layout)
        }
        
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        }
       
        required init?(coder: NSCoder) {
            super.init(coder: coder)
        }
        
        var scrollSpeed: CGPoint = .zero {
            didSet {
                guard scrollSpeed != .zero else {
                    displayLink?.isPaused = true
                    return
                }
                guard displayLink == nil else {
                    lastFrameTime = CACurrentMediaTime()
                    displayLink?.isPaused = false
                    return
                }
                lastFrameTime = CACurrentMediaTime()
                displayLink = CADisplayLink(target: self, selector: #selector(updateContentOfffset))
                displayLink?.add(to: .main, forMode: .common)
            }
        }
        
        @objc func updateContentOfffset() {
            
            defer {
                lastFrameTime = CACurrentMediaTime()
            }
            
            guard let lastFrameTime = lastFrameTime else { return }
            
            let dt = CACurrentMediaTime() - lastFrameTime
            let dx = scrollSpeed.x * CGFloat(dt)
            let dy = scrollSpeed.y * CGFloat(dt)
            
            var currentOffset = collectionView.contentOffset
            currentOffset.x += dx
            currentOffset.y += dy
            collectionView.setContentOffset(currentOffset, animated: false)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      相关资源
      最近更新 更多