這樣的層次結(jié)構(gòu)
---A
? ? ? ?---B
? ? ? ?---C
? ? ? ? ? ? ? ---D
既A包含B和C,C包含D
當(dāng)C的書信clipsTobounds為NO的時(shí)候年柠,運(yùn)行之后顯示這樣的結(jié)果:
當(dāng)我們點(diǎn)擊D超出C的部分時(shí)候,將會(huì)是誰響應(yīng)事件尼褪迟?
對(duì)的冗恨,這就是打印的結(jié)果,是不是非常吃驚味赃!為什么會(huì)出現(xiàn)這樣的結(jié)果尼掀抹?道理其實(shí)非常簡單,當(dāng)屏幕收到一個(gè)觸摸事件的時(shí)候心俗,就會(huì)開始進(jìn)行命中測試既hit-test傲武,大致的過程如下:
1. ?判斷UIApplication是否命中觸摸事件,是的城榛!就將事件傳遞給window揪利。
2. ?判斷window是否命中了事件,是的狠持!就將事件傳遞給controller疟位。
3. ?判斷controller是否命中事件,是的喘垂!就將事件傳遞給controller的rootview甜刻。
4. ?以此類推,判斷Aview是否命中事件正勒,是的得院!就會(huì)遍歷它所有的子view,分別判斷每個(gè)子view是否命中事件章贞,發(fā)現(xiàn)Bview沒有命中事件祥绞,就停止對(duì)Bview的hit-test。發(fā)現(xiàn)Cview也沒有命中事件鸭限,就停止了對(duì)Cview及其子view的hit-test就谜。
5. ?這樣一來在整個(gè)響應(yīng)者層級(jí)中,最頂端(注意:整個(gè)響應(yīng)者鏈就是一顆多叉樹)命中觸摸事件的view就是A(因?yàn)锳的直接子view沒有命中事件),因此系統(tǒng)認(rèn)為A就是最適合處理該事件的響應(yīng)者里覆,稱為第一響應(yīng)者具備了優(yōu)先響應(yīng)事件處理的能力丧荐。所以就會(huì)出現(xiàn)如上的打印咯!
那么問題來了喧枷,怎么樣才能讓點(diǎn)擊D超出C的部分時(shí)候D也能響應(yīng)尼虹统?我們知道弓坞,雖然我們點(diǎn)擊事件發(fā)生在D區(qū)域內(nèi),但是不在C區(qū)域類车荔,而C是D的父親渡冻,故父view不能命中事件,從而導(dǎo)致了子view也不能命中事件忧便。
那么解決的突破口就在于如何讓C進(jìn)行命中測試(hit-test)的時(shí)候能夠命中事件族吻。OK!只需要在C中重寫方法-(UIView*)hitTest:(CGPoint)point?withEvent:(UIEvent*)event就行啦,具體的代碼如下:
大家應(yīng)該知道珠增,在進(jìn)行命中測試的時(shí)候會(huì)調(diào)用hitTest:withEvent:方法超歌,故在此我們重寫了該方法。現(xiàn)在就能達(dá)到我們想要的效果啦蒂教!
示例代碼在此:示例代碼