一、系統是怎么找到接收觸摸事件發生的視圖的? --只通過UIView及其子類查找
0 調用根視圖的hitTtest:withEvent,其的執行過程如下:
- Ie calls pointInside:withEvent:of self
- If the return is NO,
hitTest:withEvent:
returnsnil
. the end of the story. - If the return is YES, it sends
hitTest:withEvent:
messages to its subviews. it starts from the top-level subview, and continues to other views until a subview returns a non-nil
object, or all subviews receive the message. - If a subview returns a non-
nil
object in the first time, the firsthitTest:withEvent:
returns that object. the end of the story. - If no subview returns a non-
nil
object, the firsthitTest:withEvent:
returnsself
參考:這里
二 、觸摸事件是如何傳遞的?
三、hitTest:withEvent應用:
1)父視圖中有布局重疊的且都可響應用戶操作的對象,如:ScrollView and Button,如果Button在ScrollView下面,正常情況下Button是不會成為第一響應者的,如果想讓Button可以響應在其布局內的觸摸事件,可以在Button和ScrollView的父View中重寫hitTest:withEvent方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGPoint hitPoint = [_testButton convertPoint:point fromView:self]; if ([_testButton pointInside:hitPoint withEvent:event]) return _testButton; return [super hitTest:point withEvent:event]; }//_testButton是指定響應對象的 弱 引用
參考:這里
2)UIView的子類不響應觸摸事件,但其子View可以響應。通過設置userInteractionEnabled=NO,可以使UIView子類不響應觸摸事件,但其會挾持子View,原因見3)
這時,可以通過重寫hitTest:withEvent來實現:
-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event { id hitView = [super hitTest:point withEvent:event]; if (hitView == self) return nil; else return hitView; }
參考:這里
3) userInteractionEnabled = NO的作用:使當前的hitTest:withEvent返回nil,其它的類似屬性還有:Hidden=YES,alpha<0.01,(UIControl中Enabled=NO??),事件發生的點在子View的幾何范圍內,卻超過了父View的幾何范圍(clipsToBounds=NO時可出現此種情況)
參考:
1.官方文檔