将UIPanGestureRecognizer和UISwipeGestureRecognizer添加到相同视图会导致设置requireGestureToFail

我在相同的视图中添加了滑动手势识别器和平移手势识别器。 这些手势应该是相互排斥的。

为了做到这一点,我添加了滑动手势的约束

[swipeGesture requireGestureToFail:panGesture]; 

(因为平移手势应该优先)

问题在于平移手势总是被调用 – 即使在非常快速的滑动过程中也是如此。

为了达到这个目的,我把自己定位为泛姿态的代表。 在委托方法中,我设置了一些代码如下:

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { // check if it is the relevant view if (gestureRecognizer.view == self.myViewWithTwoGestures) { // check that it is the pan gesture if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer; CGPoint velocity = [pan velocityInView:gestureRecognizer.view]; // added an arbitrary velocity for failure if (ABS(velocity.y) > 100) { // fail if the swipe was fast enough - this should allow the swipe gesture to be invoked return NO; } } } return YES; } 

有一个build议的速度,以确保良好的行为? 是否有另一种方式来强制平移手势失败?

根据Apple的文档(在两个手势识别器的声明特定顺序下),使UIPanGestureRecognizerUISwipeGestureRecognizer在同一个视图上工作的方法是在调用UIPanGestureRecognizer (与您所写的相反)之前,要求UISwipeGesureRecognizer失败。 这可能与这个事实有关,一个轻扫手势也是一个平移手势,但相反不一定是真实的(见这个SO问题)。

我写了这个小小的代码,并设法识别平移和滑动手势:

 UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panned:)]; UISwipeGestureRecognizer * swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swiped:)]; [pan requireGestureRecognizerToFail:swipe]; swipe.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight); -(void)panned:(UIPanGestureRecognizer *)gesture { NSLog(@"Pan"); } -(void)swiped:(UISwipeGestureRecognizer *)gesture { NSLog(@"Swipe"); } 

这不能像你希望的那样工作(因为你需要滑动手势失败,在平移手势开始之前有一个小的延迟),但它确实有效。 您发布的代码让您可以根据自己的喜好微调手势。

迟到的回应,但我有一个类似的问题,我想泛在刷卡之前被认出。 唯一能让它工作的方法是使用长按(或类似的东西)来设置一个标志来使用平移手势作为平移或滑动。 我最终没有使用滑动。 即:

 - (void) handleLongPress : (UILongPressGestureRecognizer *) gestureRecognizer { if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { _canSwipe = YES; } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { _canSwipe = NO; } } - (void) handleDragging : (id) sender { UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)sender; GLKVector2 dragDelta = GLKVector2Make(0., 0.); if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged) { _mousePosition = [pan translationInView:self.view]; if (_beginDragging == NO) { _beginDragging = YES; } else { dragDelta = GLKVector2Make(_mousePosition.x - _prevMousePosition.x, _mousePosition.y - _prevMousePosition.y); } _prevMousePosition = _mousePosition; } else { _beginDragging = NO; } if (_canSwipe == YES) { if (dragDelta.x > 0) { _canSwipe = NO; [self.navigationController popToRootViewControllerAnimated:YES]; NSLog(@"swipe right"); } else if (dragDelta.x < 0) { _canSwipe = NO; [self performSegueWithIdentifier:@"toTableSegue" sender:pan]; NSLog(@"swipe left"); } } else { _dragDeltaTranslation = GLKVector2Make(dragDelta.x/90, dragDelta.y/90); _translationXY = GLKVector2Make(_translationXY.x + _dragDeltaTranslation.x, _translationXY.y - _dragDeltaTranslation.y); } } 

所以基本上:

  1. 使用长按(或其他一些机制)来激活滑动状态(长按是很好的,因为一旦你释放,状态转到UIGestureRecognizerStateEnded)
  2. 然后使用平移方向确定滑动的方向。 2。