我正在尝试在我的ViewController(有一个tableView)中实现两个必须一个接一个地工作的手势识别器。第一个是向下滑动手势,第二个是长按手势。
这是我用@sergio建议修改的代码
- (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时没有日志
答案 0 :(得分:1)
为此你需要创建自己的自定义手势识别器。最好的方法是让你继续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>
的简单方法是在滑动操作中设置全局标记(在执行滑动操作时设置它;然后自定义识别器读取其值)。这是 easy ,到目前为止还不是您能找到的最佳实现。
另一种方法是依靠requiresGestureRecognizerToFail
链接3个标准手势识别器,我们称之为A,B和C,其中:
UISwipeGestureRecognizer
; UILongPressGestureRecognizer
; 您可以像这样配置它们:
C --> B --> A
x --> y
表示x
要求y
失败。因此,您C
(您的长按手势识别器)将需要B
GR失败并且B
要求A
(您的滑动识别器)失败;只要B
识别出滑动,A
就会失败;一旦B
失败,C
将被允许识别长按(如果有的话)。
编辑:
阅读完您的评论后,您是否介意尝试一下,看看是否有帮助:
删除被覆盖的touchesBegan
并将其替换为:
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
}
然后定义:
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
if (vc.methodHasBeenCalled) {
[super touchesBegan:touches withEvent:event];
} else {
return;
}
}
如果这不起作用,那么让自定义手势识别器继承自通用手势识别器和
保留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;
答案 1 :(得分:0)
如果我没有弄错的话,一旦系统检测到特定类型的手势(轻击,轻扫,平移,长按等),它就不能再为该触摸动作发送不同类型的手势。
这并不妨碍您达到预期的效果。也许是重载以下UIResponder
方法的组合:
– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
使用手势识别器(不确定输入是否被一个人消耗而被其他人忽略),您可以确定它是“长扫描”