How to have a UISwipeGestureRecognizer AND UIPanGestureRecognizer work on the same view
You're going to want to set one of the two UIGestureRecognizer
's delegates to an object that makes sense (likely self
) then listen, and return YES
for this method:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer: (UIGestureRecognizer *)otherGestureRecognizer { return YES;}
This method is called when recognition of a gesture by either gestureRecognizer
or otherGestureRecognizer
would block the other gesture recognizer from recognizing its gesture. Note that returning YES
is guaranteed to allow simultaneous recognition; returning NO
, on the other hand, is not guaranteed to prevent simultaneous recognition because the other gesture recognizer's delegate may return YES
.
By default, when the user attempts to swipe, the gesture is interpreted as a pan. This is because a swiping gesture meets the necessary conditions to be interpreted as a pan (a continuous gesture) before it meets the necessary conditions to be interpreted as a swipe (a discrete gesture).
You need to indicate a relationship between two gesture recognizers by calling the requireGestureRecognizerToFail: method on the gesture recognizer that you want to delay
[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
Using a pan recognizer to detect swipping and panning:
- (void)setupRecognizer{ UIPanGestureRecognizer* panSwipeRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanSwipe:)]; // Here you can customize for example the minimum and maximum number of fingers required panSwipeRecognizer.minimumNumberOfTouches = 2; [targetView addGestureRecognizer:panSwipeRecognizer];}#define SWIPE_UP_THRESHOLD -1000.0f#define SWIPE_DOWN_THRESHOLD 1000.0f#define SWIPE_LEFT_THRESHOLD -1000.0f#define SWIPE_RIGHT_THRESHOLD 1000.0f- (void)handlePanSwipe:(UIPanGestureRecognizer*)recognizer{ // Get the translation in the view CGPoint t = [recognizer translationInView:recognizer.view]; [recognizer setTranslation:CGPointZero inView:recognizer.view]; // TODO: Here, you should translate your target view using this translation someView.center = CGPointMake(someView.center.x + t.x, someView.center.y + t.y); // But also, detect the swipe gesture if (recognizer.state == UIGestureRecognizerStateEnded) { CGPoint vel = [recognizer velocityInView:recognizer.view]; if (vel.x < SWIPE_LEFT_THRESHOLD) { // TODO: Detected a swipe to the left } else if (vel.x > SWIPE_RIGHT_THRESHOLD) { // TODO: Detected a swipe to the right } else if (vel.y < SWIPE_UP_THRESHOLD) { // TODO: Detected a swipe up } else if (vel.y > SWIPE_DOWN_THRESHOLD) { // TODO: Detected a swipe down } else { // TODO: // Here, the user lifted the finger/fingers but didn't swipe. // If you need you can implement a snapping behaviour, where based on the location of your targetView, // you focus back on the targetView or on some next view. // It's your call } }}