结合轻扫和长按

我试图在我的ViewController(它有一个tableView)两个手势识别器,必须一个接一个地工作。 第一个是向下滑动手势,第二个是长按手势。

这是我的代码修改@sergiobuild议

- (void)viewDidLoad { [super viewDidLoad]; swipeDown = [[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeDownAction)] autorelease]; longPress = [[[CustomLongPress alloc]initWithTarget:self action:@selector(longPressAction)] autorelease]; longPress.minimumPressDuration = 2; swipeDown.numberOfTouchesRequired = 1; swipeDown.direction = UISwipeGestureRecognizerDirectionDown; swipeDown.delegate = self ; longPress.delegate = self ; [myTableView addGestureRecognizer:swipeDown]; [myTableView addGestureRecognizer:longPress]; } -(void)swipeDownAction { _methodHasBeenCalled = YES; // bool @property declared in .h NSLog(@"Swipe down detected"); } -(void)longPressAction { NSLog(@"long press detected"); } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } 

而我的UILongPressGestureRecognizer子类:

 #import "CustomLongPress.h" #import "ViewController.h" @interface CustomLongPress() { ViewController *vc; } @end @implementation CustomLongPress -(id)initWithTarget:(id)target action:(SEL)action controller:(ViewController *)viewCon { self = [super initWithTarget:target action:action]; if (self) { vc = viewCon; } return self; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(vc.methodHasBeenCalled ? @"Yes" : @"No"); if (vc.methodHasBeenCalled) { [super touchesBegan:touches withEvent:event]; } } 

不幸的是,我仍然只能得到swipeDown的日志,但是在使用longPress时却没有日志

为此,您需要创build自己的自定义手势识别器。 最好的办法是让你UILongPressGestureRecognizer并在刷卡结束之后让它“接受”长按。 例如,在touchesBegan方法

 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { <if swipe recognizer action method has been called> [super touchesBegan:touches withEvent:event]; } } 

通过这种方式,两个手势识别器都会尝试识别该手势:滑动识别器将立即这样做; 而自定义识别器将“等待”滑动识别器已被触发。

一个简单的方法来实现条件<if swipe recognizer action method has been called>将设置一个全局标志在你的滑动动作(你设置它,当滑动动作执行;然后自定义识别器读取它的值)。 这很容易 ,到目前为止,还不是最好的实现。

另一种方法是依靠requiresGestureRecognizerToFail来链接3个标准手势识别器,我们称它们为A,B和C,其中:

  1. A是一个UISwipeGestureRecognizer ;
  2. C是UILongPressGestureRecognizer ;
  3. B是任何手势识别器。

你像这样configuration它们:

 C --> B --> A 

由此x --> y表示x要求y失败。 因此,你会有C (你的长按手势识别器)将要求B GR失败和B要求A (你的滑动识别器)失败; 只要A会识别出滑动, B就会失败; 一旦B失败, C将被允许​​识别长按(如果有的话)。

编辑:

阅读你的评论后,你会介意尝试这个,看看是否有帮助:

  1. 删除重写的touchesBegan并将其replace为:

     - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { } 
  2. 然后定义:

     - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { if (vc.methodHasBeenCalled) { [super touchesBegan:touches withEvent:event]; } else { return; } } 

如果这不起作用,那么使您的自定义手势识别器inheritance自一般手势识别器和

  1. 留下touchesBegan:到位,并取代touchesMoved与:

     - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { self.lastTouch = [touches anyObject]; if (vc.methodHasBeenCalled && self.gestureNotBegunYet == YES) { self.gestureNotBegunYet = NO; [self performSelector:@selector(recognizeLongPress) withObject:nil afterDelay:1.0]; } else { return; } } 

并添加:

 - (float)travelledDistance { CGPoint currentLocation = [self.lastTouch locationInView:self.view.superview]; return sqrt(pow((currentLocation.x - self.initialLocation.x), 2.0) + pow((currentLocation.y - self.initialLocation.y), 2.0)); } - (void)fail { self.gestureNotBegunYet = YES; [NSObject cancelPreviousPerformRequestsWithTarget:self]; } - (void)recognizeLongPress { if ([self travelledDistance] < kTapDragThreshold) { self.longPressed = YES; self.state = UIGestureRecognizerStateChanged; } else { [self fail]; self.state = UIGestureRecognizerStateFailed; } } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { [self fail]; [super touchesEnded:touches withEvent:event]; } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [self fail]; [super touchesCancelled:touches withEvent:event]; } 

您将需要在.h定义

 @property(nonatomic) CGPoint initialLocation; @property(nonatomic, retain) UITouch* lastTouch; @property(nonatomic) BOOL gestureNotBegunYet; 

如果我没有弄错,一旦系统检测到特定types的手势(点击,滑动,平移,长按等),就不能再为该触摸动作发送不同types的手势。

这并不妨碍你达到你想要的结果。 也许重载下面的UIResponder方法的组合:

 – touchesBegan:withEvent: – touchesMoved:withEvent: – touchesEnded:withEvent: – touchesCancelled:withEvent: 

并且使用一个手势识别器(不知道input是否被一个人使用而被另一个忽略),你可以确定这是一个“长扫”