结合轻扫和长按
我试图在我的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,其中:
- A是一个
UISwipeGestureRecognizer
; - C是
UILongPressGestureRecognizer
; - B是任何手势识别器。
你像这样configuration它们:
C --> B --> A
由此x --> y
表示x
要求y
失败。 因此,你会有C
(你的长按手势识别器)将要求B
GR失败和B
要求A
(你的滑动识别器)失败; 只要A
会识别出滑动, B
就会失败; 一旦B
失败, C
将被允许识别长按(如果有的话)。
编辑:
阅读你的评论后,你会介意尝试这个,看看是否有帮助:
-
删除重写的
touchesBegan
并将其replace为:- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { }
-
然后定义:
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { if (vc.methodHasBeenCalled) { [super touchesBegan:touches withEvent:event]; } else { return; } }
如果这不起作用,那么使您的自定义手势识别器inheritance自一般手势识别器和
-
留下
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是否被一个人使用而被另一个忽略),你可以确定这是一个“长扫”