0
votes

My app uses a paged horizontal scroll view. Each page has UIControls which the user can tap.

UIScrollView does a good job of handling cancellation of touches and swipes. If the user starts swiping fast enough, it's always a swipe. If the user touches down long enough to activate the highlighted state, the scroll view doesn't attempt to swipe.

I'm trying to duplicate this behavior with a UIPanGestureRecognizer subclass so that I can respond to downward swipes within my scrollview. However, I can't get the gesture to cancel in the event of the UIControls getting highlighted.

So far I've done the following:

self.refreshGesture.cancelsTouchesInView = YES;
self.refreshGesture.delaysTouchesBegan = NO;
self.refreshGesture.delaysTouchesEnded = NO;

This seems to duplicate the way UIScrollView passes touches to views, but it doesn't duplicate the way that UIScrollView's pan gesture recognizer gets cancelled. self.refreshGesture is always triggered no matter how slowly the user swipes, or what the state of the UIControls are.

I've tried setting the delegate on my gesture, and this may be the way to go. But I haven't found a combination that works. For example, just checking if the touch starts within a UIControl cancels too frequently. I've also tried overriding gestureRecognizerShouldBegin in my controls, but this seems like a hack and has far reaching implications (interferes with UITextView's gestures, for example).

In this GIF, you can see that the control activates on touch, and the scrollview cancels scroll if that happens. But my downward pan gesture is not cancelled in the same manner:

enter image description here

1

1 Answers

0
votes

I wasn't able to duplicate this exactly, but there are two possibilities suggested by WWDC 2014 #235.

  1. Add a transparent scrollview over your main content and move its gesture recognizer onto your root view. This is what did. It let me use UIScrollViewDelegate which ended up being sufficient.
  2. Use a "timeout" gesture recognizer. The video suggests requiring the timeout gesture to fail, but in my case it worked better to use a long press gesture and cancel my pan if the long press fired. 0.1 seconds seemed to work better than their suggested 0.15 seconds.