【问题标题】: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)
}
}