There are myriad answers on cancelling a UIScrollView
's touches (example SO question). However, the generally accepted answer (see prior example) is to do this by directly cancelling the scrollView's gesture recogniser, as below:
// Reset a scrollView's current 'touch'
scrollView.panGestureRecognizer.enabled = false
scrollView.panGestureRecognizer.enabled = true
The issue I'm currently having with this solution is that it cancels the ability for the scrollView to animate smoothly, and results in jumpy behaviour once you try to manipulate/animate the scrollView's contentOffset
property.
In short, what I am trying to do is: once a paged scrollView reaches a certain content offset above its current page, cancel the current touch on the scrollView, animate back to the current page, and only then allow touches once more. You can liken this to having a scrollView containing a deck of cards that are only able to be scrolled through in one direction — if you attempt to go back (up) a card in the scrollView, you are stopped at a certain offset and the scrollView force-animates back down to the card you were on.
[Note — I understand there are other, more efficient ways to do this with gesture recognisers and custom views, but my need for a scrollView is more nuanced]
My code below (via my scrollView's delegate), cancels the current touch, but does not allow animation to happen. It simply 'snaps' back to place. Interestingly, without the pan gesture reset, the animation does happen — but of course since the pan gesture has not been reset the touch is allowed to continue dragging (even with userInteractionEnabled
set to 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
}
})
}
}
Any thoughts? Hopefully I'm missing something...