使用 UIPanGestureRecognizer 以给定速度滚动 UICollectionView



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

似乎没有一个 API 可以在UIScrollViewUICollectionView中以给定的速度滚动。是否有任何聪明的方法可以使用现有方法(例如scrollToVisibleRect或在动画块中设置内容偏移量(来做到这一点?我担心虽然这些可能有效,但它们的运动会生涩!

我最终为此创建了一个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)
}
}

最新更新