這樣的層次結構
---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:方法,故在此我們重寫了該方法。現在就能達到我們想要的效果啦!
示例代碼在此:示例代碼