创建一个捕捉点击但对所有其他手势透明的 UIView

Posted

技术标签:

【中文标题】创建一个捕捉点击但对所有其他手势透明的 UIView【英文标题】:Creating a UIView that captures taps, but is transparent to all other gestures 【发布时间】:2012-11-16 08:28:09 【问题描述】:

我想实现以下目标。

场景:ios 键盘在用户输入特定文本字段时显示在屏幕上。用户可以点击键盘和文本字段之外的任何地方来关闭键盘(无需激活任何可见的按钮)。此外,用户可以拖动到键盘外并观察一些可滚动视图排列的正常拖动行为。

从概念上讲,我在大部分屏幕上放置了一个“封面”UIView,其行为如下:

    如果用户点击封面,我会捕捉该点击(这样我就可以关闭键盘)。这很容易通过在UIView 子类中拦截触摸事件或使用轻击手势识别器来实现。

    如果用户在封面上拖动,则封面忽略向前这些触摸;这些被下面的层接收,就像没有覆盖一样。

所以:用户应该能够滚动封面下方的内容,但不能点击封面下方的内容。在键盘和文本字段的“外部”轻按应该会关闭键盘(和覆盖),但不应激活任何东西。

我怎样才能做到这一点?

【问题讨论】:

您必须考虑实现触摸委托方法并将触摸传递给其背后的视图以进行滑动。 - (void) touchesBegan:(NSSet*) touches withEvent:(UIEvent*)event [otherView touchesBegan:touches withEvent:event]; 另一种方式是实现,UIPanGestureRecognizer,设置cancelsTouchesInView = YES为UIPanGestureRecognizer *gr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan)]; [gr setCancelsTouchesInView:YES]; [myButton addGestureRecognizer:gr]; [gr release]; @mjh,你找到解决办法了吗? 【参考方案1】:

以通常的方式添加点击手势:

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self.view addGestureRecognizer:tapGesture];

但您可能正在寻找的是:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
        
        return YES;
    

文档说:当通过gestureRecognizer 或otherGestureRecognizer 识别手势会阻止其他手势识别器识别其手势时调用此方法。 (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizerDelegate_Protocol/index.html#//apple_ref/occ/intf/UIGestureRecognizerDelegate)

这样,您可以确定它是完全透明的,并且没有什么会阻止您的识别器被调用。

【讨论】:

【参考方案2】:

转发它收到的所有触摸的自定义视图:

class CustomView: UIView 

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? 

        var hitView = super.hitTest(point, withEvent: event)

        if hitView == self 
            return nil
        

        return hitView
        

从那里你可以通过不同的方式来使用点击手势。观察 UIEvent 的触摸,或使用手势识别器。

【讨论】:

【参考方案3】:

1:在视图中添加点击手势识别器:

    //Adding tap gesture
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
    tapGesture.numberOfTapsRequired = 1;
    [self.view addGestureRecognizer:tapGesture];

2:在handleTapGesture中你resignFirstResponder的键盘

- (void)handleTapGesture:(UITapGestureRecognizer *)sender 
    if (sender.state == UIGestureRecognizerStateRecognized) 
       //Resign first responder for keyboard here
    

对上面的答案进行了详细说明。 UIGestureRecognizerStateRecognized 确保它是被识别的单个选项卡事件。

这是你追求的功能吗?

【讨论】:

他的问题是“如果用户在封面上拖动,那么封面会忽略所有触摸;这些触摸会被下面的图层接收,就像没有封面一样。”。他已经想出了如何检测触摸。 如果UIView 能够识别点击,那么它的.userInteractionEnabled 必须是YES,因此它会吃掉所有的触摸事件,防止拖动被下面的任何东西识别。

以上是关于创建一个捕捉点击但对所有其他手势透明的 UIView的主要内容,如果未能解决你的问题,请参考以下文章

iOS点击识别器捕捉所有点击

在 SwiftUI 中的表单上捕捉点击手势

UI 平移手势不起作用

为啥将 UILabel 设置为完全透明会丢失点击手势?

透明后如何检测 UIView 上的手势?

如何在 Xamarin.Forms 的主页上禁用主页点击手势而不是其他页面?