美文网首页iOS技术程序员iOS Developer
【iOS 开发】父视图外部子视图点击响应 - hitTest

【iOS 开发】父视图外部子视图点击响应 - hitTest

作者: KyXu | 来源:发表于2016-08-19 11:33 被阅读750次

面试被问过两次了的一个问题,记录一下:假如一个 UIView(我们称作 FatherView),有一个 subview(我们称作 ChildView),这个 ChildView 在 FatherView 的 frame 外部,那么默认情况下,这个 ChildView 被点击的时候,并不会触发 FatherView 的点击响应链(这是合情合理的,FatherView 所在的位置都没被点击,它不遍历 subviews,不作回应是正常的),这时候怎样才能让这个 ChildView 相应点击事件?

其实思路是很简单的,监控屏幕上的所有点击事件的区域,如果这个区域和我们的 UIView 以及其 subview 的 CGRect 有重合,就作出反应。

也很容易查到 UIKit 提供了一个现成的方法来做到这件事:


Hit Testing in a View Screen Shot

代码是很简单的,现在让灰色的视图作为父视图,蓝色、红色的作为子视图,只要灰色视图实现了上述方法,就可以让蓝色视图像红色视图一样,可以相应点击事件。

Code Snippet Code Snippet

完整 Demo Github 地址

至此都是很简单的内容,需要注意的如下:

  • 你会发现 FatherView 里面的这个 <code>HitTest</code> 会被频繁执行,你随便点击一个空白处,这个方法都会执行,这必然带来性能消耗,这也是 Apple 默认不使用这个方式的原因之一吧
  • <code>HitTest</code> 会使得我们的蓝色的 UIView 可以相应点击,但是它被点击的之后,执行的方法我们应该按常规的方式写(比如给它加一个 <code>UIGestureRecognizer</code> ,然后让这个 Gesture 有一个对应的 selector)。如果把需要执行的方法写在了 <code>HitTest</code> 里面,写在 <code>return result</code> 之前的话,我发现这些方法会多执行一次(在我当前写的这个简单 demo 里,我发现点击任意地方,<code>HitTest</code> 方法都会连续执行两次)

延伸阅读 - 深入浅出 iOS 事件机制

相关文章

网友评论

  • 红烧大鸡腿:请问一下:为什么轻触屏幕时,每个相关view的testView会响应两次?
    红烧大鸡腿:@KyXu 这个问题好奇怪,昨天查了半天也没找到原因....
    KyXu:@HCX_IOS 不知道:sweat:
  • peerben:这个代码写的有些啰嗦


    class HitView: UIView {

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

    for view in self.subviews {

    if CGRectContainsPoint(view.frame, point) {
    return view
    }
    }
    return super.hitTest(point, withEvent: event)
    }
    }
    peerben:@广锅锅 赞:+1:,大意了
    广锅锅:@peerben 是有点啰嗦,不过按照苹果的官方文档,你这个也有不合理的地方
    ```
    CGPoint pointForTargetView = [self.targetView convertPoint:point fromView:self];
    if (CGRectContainsPoint(self.targetView.bounds, pointForTargetView)) {
    return [self.targetView hitTest:pointForTargetView withEvent:event];
    }
    return [super hitTest:point withEvent:event];
    ```
    应该把点击位置转换到目标视图的坐标系中再做包含判断。

本文标题:【iOS 开发】父视图外部子视图点击响应 - hitTest

本文链接:https://www.haomeiwen.com/subject/vxdbsttx.html