优雅取消 UIScrollView 触摸(带动画)
Gracefully cancel UIScrollView touch (with animation)
关于取消 UIScrollView
的触摸 (example SO question) 有无数的答案。然而,普遍接受的答案(见前面的例子)是通过直接取消scrollView的手势识别来做到这一点,如下:
// Reset a scrollView's current 'touch'
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
我目前遇到的这个 解决方案 的问题是它取消了 scrollView 平滑动画的能力,并且一旦你尝试 manipulate/animate scrollView的contentOffset
属性.
简而言之,我想做的是:一旦 分页滚动视图 达到其当前页面上方的某个内容偏移量,取消滚动视图上的当前触摸,动画返回到当前页面,然后才允许再次触摸。你可以把它比作一个包含一副纸牌的滚动视图,这些纸牌只能在一个方向上滚动——如果你试图返回(向上)滚动视图中的一张卡片,你会停在某个偏移量处,滚动视图强制动画回到您所在的卡片。
[注意 — 我知道还有其他更有效的方法可以使用手势识别器和自定义视图来执行此操作,但我对 scrollView 的需求更加微妙]
我下面的代码(通过我的 scrollView 的委托)取消了当前触摸,但不允许动画发生。它只是 'snaps' 回到原位。有趣的是,在没有重置平移手势的情况下,动画确实发生了——但当然,由于没有重置平移手势,因此允许触摸继续拖动(即使 userInteractionEnabled
设置为 false)。
// Delegate methods
func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y <= (scrollView.frame.height PAGE_NUMBER - OFFSET_MARKER) {
// Where PAGE_NUMBER is the current page, and OFFSET_MARKER is the amount of pixels to trigger at, i.e. 80px
// Temporarily stop further user interaction
scrollView.userInteractionEnabled = false
// Reset the pan gesture recogniser -- THIS CAUSES 'SKIPPING' OF ANIMATION
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
// I have tried both 'animated: true / false'
UIView.animateWithDuration(0.4, animations: {
scrollView.setContentOffset(CGPointMake(0, self.frame.height), animated: true)
}, completion: { (complete) in
if complete{
// Re-enable user interaction (more touches)
scrollView.userInteractionEnabled = true
}
})
}
}
有什么想法吗?希望我遗漏了什么...
原来 snapiness 归因于暂时禁用 panGestureRecognizer
源于正在分页的 scrollView。因此,将 scrollView.pagingEnabled
属性 设置为 false(暂时在委托中)为我解决了这个问题。
不确定为什么会这样,但我会做更多的挖掘工作并可能提交错误报告。
关于取消 UIScrollView
的触摸 (example SO question) 有无数的答案。然而,普遍接受的答案(见前面的例子)是通过直接取消scrollView的手势识别来做到这一点,如下:
// Reset a scrollView's current 'touch'
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
我目前遇到的这个 解决方案 的问题是它取消了 scrollView 平滑动画的能力,并且一旦你尝试 manipulate/animate scrollView的contentOffset
属性.
简而言之,我想做的是:一旦 分页滚动视图 达到其当前页面上方的某个内容偏移量,取消滚动视图上的当前触摸,动画返回到当前页面,然后才允许再次触摸。你可以把它比作一个包含一副纸牌的滚动视图,这些纸牌只能在一个方向上滚动——如果你试图返回(向上)滚动视图中的一张卡片,你会停在某个偏移量处,滚动视图强制动画回到您所在的卡片。
[注意 — 我知道还有其他更有效的方法可以使用手势识别器和自定义视图来执行此操作,但我对 scrollView 的需求更加微妙]
我下面的代码(通过我的 scrollView 的委托)取消了当前触摸,但不允许动画发生。它只是 'snaps' 回到原位。有趣的是,在没有重置平移手势的情况下,动画确实发生了——但当然,由于没有重置平移手势,因此允许触摸继续拖动(即使 userInteractionEnabled
设置为 false)。
// Delegate methods
func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y <= (scrollView.frame.height PAGE_NUMBER - OFFSET_MARKER) {
// Where PAGE_NUMBER is the current page, and OFFSET_MARKER is the amount of pixels to trigger at, i.e. 80px
// Temporarily stop further user interaction
scrollView.userInteractionEnabled = false
// Reset the pan gesture recogniser -- THIS CAUSES 'SKIPPING' OF ANIMATION
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
// I have tried both 'animated: true / false'
UIView.animateWithDuration(0.4, animations: {
scrollView.setContentOffset(CGPointMake(0, self.frame.height), animated: true)
}, completion: { (complete) in
if complete{
// Re-enable user interaction (more touches)
scrollView.userInteractionEnabled = true
}
})
}
}
有什么想法吗?希望我遗漏了什么...
原来 snapiness 归因于暂时禁用 panGestureRecognizer
源于正在分页的 scrollView。因此,将 scrollView.pagingEnabled
属性 设置为 false(暂时在委托中)为我解决了这个问题。
不确定为什么会这样,但我会做更多的挖掘工作并可能提交错误报告。