这样的层次结构
---A
---B
---C
---D
既A包含B和C,C包含D
当C的书信clipsTobounds为NO的时候,运行之后显示这样的结果:
当我们点击D超出C的部分时候,将会是谁响应事件尼?
对的,这就是打印的结果,是不是非常吃惊!为什么会出现这样的结果尼?道理其实非常简单,当屏幕收到一个触摸事件的时候,就会开始进行命中测试既hit-test,大致的过程如下:
1. 判断UIApplication是否命中触摸事件,是的!就将事件传递给window。
2. 判断window是否命中了事件,是的!就将事件传递给controller。
3. 判断controller是否命中事件,是的!就将事件传递给controller的rootview。
4. 以此类推,判断Aview是否命中事件,是的!就会遍历它所有的子view,分别判断每个子view是否命中事件,发现Bview没有命中事件,就停止对Bview的hit-test。发现Cview也没有命中事件,就停止了对Cview及其子view的hit-test。
5. 这样一来在整个响应者层级中,最顶端(注意:整个响应者链就是一颗多叉树)命中触摸事件的view就是A(因为A的直接子view没有命中事件),因此系统认为A就是最适合处理该事件的响应者,称为第一响应者具备了优先响应事件处理的能力。所以就会出现如上的打印咯!
那么问题来了,怎么样才能让点击D超出C的部分时候D也能响应尼?我们知道,虽然我们点击事件发生在D区域内,但是不在C区域类,而C是D的父亲,故父view不能命中事件,从而导致了子view也不能命中事件。
那么解决的突破口就在于如何让C进行命中测试(hit-test)的时候能够命中事件。OK!只需要在C中重写方法-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event就行啦,具体的代码如下:
大家应该知道,在进行命中测试的时候会调用hitTest:withEvent:方法,故在此我们重写了该方法。现在就能达到我们想要的效果啦!
示例代码在此:示例代码