美文网首页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