昨天被問(wèn)到了一個(gè)問(wèn)題,如下
一個(gè)子視圖能不能透過(guò)上層視圖來(lái)響應(yīng)自己的點(diǎn)擊事件餐抢?如果能现使,怎么實(shí)現(xiàn)?
這種題用腳想都是能啊旷痕,可怎么做碳锈??欺抗?
經(jīng)過(guò)簡(jiǎn)單研究售碳,發(fā)現(xiàn)了解決辦法。如下:
這里涉及到一個(gè)視圖的方法
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
這是在UIView(UIViewGeometry)
視圖結(jié)構(gòu)分類里面的方法绞呈,使用方法如下:
1. 背景知識(shí)
iOS系統(tǒng)檢測(cè)到手指觸摸(Touch)操作時(shí)會(huì)將其放入當(dāng)前活動(dòng)Application的事件隊(duì)列贸人,Application會(huì)從事件隊(duì)列中取出觸摸事件并傳遞給key window(當(dāng)前接收用戶事件的窗口)處理,window對(duì)象首先會(huì)使用hitTest:withEvent:
方法尋找此次Touch操作初始點(diǎn)所在的視圖(View)佃声,即需要將觸摸事件傳遞給其處理的視圖,稱之為hit-test view艺智。
window對(duì)象會(huì)在首先在view hierarchy的頂級(jí)view上調(diào)用hitTest:withEvent:
,此方法會(huì)在視圖層級(jí)結(jié)構(gòu)中的每個(gè)視圖上調(diào)用pointInside:withEvent:
圾亏,如果pointInside:withEvent:
返回YES十拣,則繼續(xù)逐級(jí)調(diào)用,直到找到touch操作發(fā)生的位置志鹃,這個(gè)視圖也就是hit-test view父晶。
2. 處理流程
- 首先調(diào)用當(dāng)前視圖的
pointInside:withEvent:
方法判斷觸摸點(diǎn)是否在當(dāng)前視圖內(nèi); - 若返回NO弄跌,則
hitTest:withEvent:
返回nil甲喝; - 若返回YES,則向當(dāng)前視圖的所有子視圖(subviews)發(fā)送
hitTest:withEvent:
消息铛只,所有子視圖的遍歷順序是從top到bottom埠胖,即從subviews數(shù)組的末尾向前遍歷,直到有子視圖返回非空對(duì)象或者全部子視圖遍歷完畢糠溜; - 若第一次有子視圖返回非空對(duì)象,則
hitTest:withEvent:
方法返回此對(duì)象直撤,處理結(jié)束非竿; - 如所有子視圖都返回非,則
hitTest:withEvent:
方法返回自身(self)谋竖。
3. 使用
直接參考代碼
// 在父視圖中實(shí)現(xiàn)方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 1.這是當(dāng)前點(diǎn)擊的視圖红柱,如果沒(méi)有找到合適的響應(yīng)操作的視圖,則直接返回這個(gè)
UIView *view = [super hitTest:point withEvent:event];
// 2.將父視圖坐標(biāo)轉(zhuǎn)成我想要響應(yīng)事件的視圖的坐標(biāo)
CGPoint buttonPoint = [self convertPoint:point toView:self.button];
// 3.判斷該坐標(biāo)是否在視圖內(nèi)部蓖乘,如果是锤悄,則返回該視圖
if ([self.button pointInside:buttonPoint withEvent:event]) {
return self.button;
}
return view;
}
代碼寫(xiě)起來(lái)也是簡(jiǎn)單明了,但有幾個(gè)注意事項(xiàng)嘉抒,如下:
- 設(shè)置
hidden = YES;
仍然是可以通過(guò)該方法響應(yīng)事件零聚。 - 設(shè)置
alpha = 0.001;
也是可以通過(guò)該方法響應(yīng)事件。 - 子視圖的 origin 即使超出父視圖的范圍也是可以響應(yīng)事件些侍。
- 設(shè)置
userInteractionEnabled = NO;
則不可以響應(yīng)事件了隶症。
這種方式可以做出很多風(fēng)騷的操作,就看各位的想象力了~