从UIGestureRecognizer中排除子视图

Awa*_*ain 32 xcode objective-c uiview uigesturerecognizer

我有一个UIView('容器视图'),其中包含几个"子视图".我想在容器视图中添加一个UITapGestureRecognizer,这样当我触摸容器视图内的区域但在子视图之外时,它会被激活.

此时,触摸容器视图内的任何位置(包括子视图内部)都会激活手势识别器.

实现看起来像这样:在控制器中:

ContainerView *containerView = [[ContainerView alloc] initWithSubViews:array];
UITapGestureRecognizer *tap = [UITapGestureRecognizer alloc] initWithTarget:self action:@selector(someSelector)];
[containerView addGestureRecognizer:tap];
[self.view addSubView:containerView];
Run Code Online (Sandbox Code Playgroud)

在ContainerView.m中

-(id)initWithSubviews:(NSArray *)array {
    for (subView *s in array) {
        [self addSubView:s];
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

我认为问题出现是因为在子视图之后添加了手势识别器.如果这是真的那么解决方案将需要将initWithSubViews方法分成两个单独的方法,我宁愿避免.

谢谢

vie*_*one 40

我用下面简单的方法.它工作得很好!

实现UIGestureRecognizerDelegate函数,只接受superview上的触摸,不接受子视图上的触摸:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (touch.view != _mySuperView) { // accept only touchs on superview, not accept touchs on subviews
        return NO;
    }

    return YES;
}
Run Code Online (Sandbox Code Playgroud)


Awa*_*ain 13

我设法通过执行以下操作来实现它:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHandler:)];

// ...

-(void) tapGestureHandler:(UITapGestureRecognizer *)sender {
    CGPoint point = [sender locationInView:sender.view];
    UIView *viewTouched = [sender.view hitTest:point withEvent:nil];
    if ([viewTouched isKindOfClass:[ThingIDontWantTouched class]]) {
        // Do nothing;
    } else {
        // respond to touch action
    }
}
Run Code Online (Sandbox Code Playgroud)


mat*_*att 13

iOS 6引入了一个很棒的新功能来解决这个问题 - 一个UIView(子视图)可以从gestureRecognizerShouldBegin:(超级视图附加的手势识别器)返回NO .实际上,对于某些手势识别器而言,这是某些UIView子类的默认值(例如关于连接到超级视图的UITapGestureRecognizer的UIButton).

请参阅我关于此主题的书:http://www.apeth.com/iOSBook/ch18.html#_gesture_recognizers


Jim*_*ney 6

记得添加和设置委托方法——

在你的 UIViewController 的 .h 文件中包含这个委托

@interface YourViewController: UIViewController<UIGestureRecogniserDelegate>
Run Code Online (Sandbox Code Playgroud)

然后你在哪里创建你的 tapGesture 对象,(例如在 viewDidLoad 中)

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(actionMethodYouWantToHappenOnTap)];  

    tap.delegate = self;  //Remember to set delegate! Otherwise the delegate method won't get called.

    [self.view addGestureRecognizer:tap];
Run Code Online (Sandbox Code Playgroud)

记住设置委托方法,tap.delegate = self;然后点击的委托方法现在将在点击时触发。

在此方法中,您可以处理何时希望使用点击手势识别,在我的代码中,如果特定子视图可见,我希望它忽略点击

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{

     if (!mySubview.hidden){
     return NO;   //This fired if said subview was visible, though whatever the condition of where and when you want tap to work, can be handled within this delegate method.
     }

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助其他有同样问题的人。记住设置我发现的委托方法很容易被忽视。

干杯