手势识别器和button操作

我有一个看起来像这样的视图层次结构:

UIView (A) UIView > UIImageView UIView > UIView (B) UIView > UIView (B) > Rounded Rect Button UIView > UIView (B) > UIImageView UIView > UIView (B) > UILabel 

我已经附加了手势识别器(S)到我的UIView(B)。 我面临的问题是,我没有得到UIView(B)内的Rounded Rect Button的任何操作。 singleTap手势识别器捕获/覆盖button的Touch Up Inside事件。

我怎样才能使它工作? 我认为响应者链接层次结构将确保button触摸事件将被给予优先,并将触发! 我错过了什么?

这里有一些相关的代码:

 #pragma mark - #pragma mark View lifecycle (Gesture recognizer setup) - (void)viewDidLoad { [super viewDidLoad]; // double tap gesture recognizer UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)]; dtapGestureRecognize.delegate = self; dtapGestureRecognize.numberOfTapsRequired = 2; [self.viewB addGestureRecognizer:dtapGestureRecognize]; // single tap gesture recognizer UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)]; tapGestureRecognize.delegate = self; tapGestureRecognize.numberOfTapsRequired = 1; [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize]; [self.viewB addGestureRecognizer:tapGestureRecognize]; // add gesture recodgnizer to the grid view to start the edit mode UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)]; pahGestureRecognizer.delegate = self; pahGestureRecognizer.minimumPressDuration = 0.5; [self.viewB addGestureRecognizer:pahGestureRecognizer]; [dtapGestureRecognize release]; [tapGestureRecognize release]; [pahGestureRecognizer release]; } #pragma mark - #pragma mark Button actions - (IBAction)buttonTouchUpInside:(id)sender { NSLog(@"%s, %@", __FUNCTION__, sender); } #pragma mark - #pragma mark Gesture recognizer actions - (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { NSLog(@"%s", __FUNCTION__); } - (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { NSLog(@"%s", __FUNCTION__); } - (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer { switch (gestureRecognizer.state) { case UIGestureRecognizerStateEnded: { NSLog(@"%s", __FUNCTION__); break; } default: break; } } 

在“shouldReceiveTouch”方法中,你应该添加一个条件,如果触摸在button中将返回NO。

这是来自苹果SimpleGestureRecognizers的例子。

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { // Disallow recognition of tap gestures in the segmented control. if ((touch.view == yourButton)) {//change it to your condition return NO; } return YES; } 

希望这会有所帮助

编辑

正如丹尼尔指出,你必须符合UIGestureRecognizerDelegate它的工作。

SHANI

我也有同样的问题,然后我尝试了

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ if ([touch.view isKindOfClass:[UIButton class]]) { //change it to your condition return NO; } return YES; } 

现在正在工作完美………

一般来说,我们使用下面的委托方法来避免在各种UIControl中触摸:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if (([touch.view isKindOfClass:[UIControl class]])) { return NO; } return YES; } 

注意:不要做这个检查(检查recognitionizer.view类的types)的gestureRecognizerShouldBegin,它不会工作。

这是一个Swift版本:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if (touch.view!.isKindOfClass(UIButton)) { return false } return true } 

不要忘记:

  1. 让你的类符合UIGestureRecognizerDelegate
  2. 让你的tapper对象委托给自己(例如: tapper.delegate = self

这里是一个Swift 3.0版本:

 extension UIViewController: UIGestureRecognizerDelegate { public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if touch.view is UIButton { return false } return true } 

不要忘记:

Make your tapper object delegate to self (eg: tapper.delegate = self)

最好的解决办法就是使用下面的代码片段:

 -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { CGPoint touchLocation = [touch locationInView:self.view]; return !CGRectContainsPoint(self.menuButton.frame, touchLocation); }