防止子视图上的 UITapGestureRecognizer

Posted

技术标签:

【中文标题】防止子视图上的 UITapGestureRecognizer【英文标题】:Prevent UITapGestureRecognizer on Subview 【发布时间】:2013-07-14 01:18:52 【问题描述】:

我不想在用户点击contentView 时调用closeShareView,只在modalView 上调用,我该怎么做?

UIWindow* mainWindow = (((AppDelegate *)[UIApplication sharedApplication].delegate).window);

// Modal view
UIView *modalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
modalView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8f];

// Content view (goes inside modalView)
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(modalView.center.x, modalView.center.y, 220, 220)];
[modalView addSubview:contentView];
[mainWindow addSubview:modalView];

// Tap gesture (added to modalView)
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeShareView:)];
gr.numberOfTapsRequired = 1;
[modalView addGestureRecognizer:gr];

【问题讨论】:

【参考方案1】:

所以您想要“在内容视图之外单击以关闭模式”之类的交易?

不要将点击手势添加到整个模态视图,而是有一个背景视图来处理它,内容视图自然会拦截所有点击(如果它启用了用户交互),所以你基本上不必这样做任何编码。

UIWindow* mainWindow = (((AppDelegate *)[UIApplication sharedApplication].delegate).window);

// Modal view
UIView *modalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Background tap view
UIView *backgroundView = [[UIView alloc] initWithFrame:modalView.bounds];
backgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
[modalView addSubview:backgroundView];

// Content view (goes inside modalView)
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(modalView.center.x, modalView.center.y, 220, 220)];
[modalView addSubview:contentView];
[mainWindow addSubview:modalView];

// Tap gesture (added to backgroundView)
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeShareView:)];
gr.numberOfTapsRequired = 1;
[backgroundView addGestureRecognizer:gr];

【讨论】:

模态视图是背景视图。即使启用了用户交互,子视图仍会识别点击。 模态视图不仅仅是背景视图,它是父视图,如果你在父视图中添加手势识别器,它会处理它,当然它不会工作所以,你可以在modalView 上添加另一个UIView(或者UIControl,如果你感觉超级懒惰),但在contentView 后面,这样就可以解决这个问题。 我实际上只是将代码复制并粘贴到一个新项目中,然后工作(这也让我感到惊讶:D)。 将 UIGestureRecognizer 切换到背景视图效果很好。很好的答案。【参考方案2】:

首先,在你的头文件中遵守UIGestureRecognizerDelegate协议。

UIGestureRecognizer 的委托设置为self

然后设置子视图的 标签 例如到 100(但你应该使用一个常数)。

然后使用类似的东西:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    CGPoint point = [gestureRecognizer locationInView:self.view];
    UIView *viewTouched = [self.view hitTest:point withEvent:nil];
    if (viewTouched.tag == 100) 
        // Don't BEGIN the gestureRecognizer
        return NO;
     else 
        // Do BEGIN the gestureRecognizer
        return YES;
    

【讨论】:

【参考方案3】:

我只是在检查被触摸的视图是否是自我,否则它是一个子视图并且手势不应该开始:

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool 
    let point = gestureRecognizer.locationInView(self.view)
    if let viewTouched = self.view.hitTest(point, withEvent: nil) where viewTouched != self.view 
        return false
     else 
        return true
    

【讨论】:

【参考方案4】:
  @objc func handleTap(_ sender: UITapGestureRecognizer)
    let point = sender.location(in: subview)
    if !(tapView.frame.contains(point)) 
        self.dismiss(animated: true, completion: nil)
    


这里,tapview 是添加点击手势的视图,subview 是它的子视图

【讨论】:

不适用于子视图下方的点击 - 它们未被识别为背景点击。【参考方案5】:

我上面有一个backgroundView 和一个tableView

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(backgroundTapped))
tapGestureRecognizer.delegate = self
backgroundView.addGestureRecognizer(tapGestureRecognizer)



// MARK: - UIGestureRecognizerDelegate

extension PhoneListViewController: UIGestureRecognizerDelegate 
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 
        let point = gestureRecognizer.location(in: self.tableView)
        return !self.tableView.point(inside: point, with: nil)
    

【讨论】:

以上是关于防止子视图上的 UITapGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 SwiftUI clipShape 影响子视图

防止父视图在子视图作用于它后接收触摸事件

防止子视图在其 Superview 转换时进行转换

调用removeFromSuperview后如何防止子视图释放自我?

防止 UIScrollView 向子视图发送触摸

防止父视图 UIGestureRecongnizer 在 UITableVIew 子视图中执行