繼承關(guān)系
UIResponder 繼承關(guān)系圖
只有繼承了UIResponder的對(duì)象才能接受并處理事件
事件傳遞
UIView是UIResponder的子類,可以覆蓋下列4個(gè)方法處理不同的觸摸事件
// 一根或者多根手指開始觸摸view,系統(tǒng)會(huì)自動(dòng)調(diào)用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
// 一根或者多根手指在view上移動(dòng),系統(tǒng)會(huì)自動(dòng)調(diào)用view的下面方法(隨著手指的移動(dòng),會(huì)持續(xù)調(diào)用該方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
// 一根或者多根手指離開view党巾,系統(tǒng)會(huì)自動(dòng)調(diào)用view的下面方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
// 觸摸結(jié)束前,某個(gè)系統(tǒng)事件(例如電話呼入)會(huì)打斷觸摸過程,系統(tǒng)會(huì)自動(dòng)調(diào)用view的下面方法
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
// 提示:touches中存放的都是UITouch對(duì)象
觸摸事件的傳遞是從父控件傳遞到子控件蕾管,遍歷子視圖的時(shí)候從后到前
也就是UIApplication->window->尋找處理事件最合適的view
判斷條件是
- 1.自身是否能夠響應(yīng)觸摸事件
- 2.觸摸點(diǎn)在不在自己身上
- 3.1 如果在則遍歷子視圖,尋找最合適的
- 3.2 如果沒有子視圖菩暗,且找不到最合適的掰曾,則自身成為最合適的響應(yīng)者
然后該類響應(yīng)touchs方法
事件攔截
如果觸摸點(diǎn)不在自身上則不去遍歷子視圖
如果在則一定會(huì)去遍歷所有子視圖,所以說不管子視圖有沒有這個(gè)點(diǎn)停团,只要父視圖有旷坦,則會(huì)默認(rèn)被遍歷一遍掏熬。
第一層的子視圖都會(huì)調(diào)用hitTest:withEvent:方法
所以只要在hitTest:withEvent:中返回哪個(gè)View,哪個(gè)View就是響應(yīng)者塞蹭。
例如:點(diǎn)擊父視圖孽江,子視圖重寫hitTest:withEvent:,返回self這樣就達(dá)到了擴(kuò)大子視圖響應(yīng)范圍的效果
如上圖番电,在橙色的圖上點(diǎn)擊岗屏,由于藍(lán)色是第一層子視圖,所以藍(lán)色會(huì)被事件傳遞一次漱办,調(diào)用了hitTest
在藍(lán)色類C中創(chuàng)建一個(gè)手勢(shì)方法这刷,并重寫hitTest返回self,這樣就能響應(yīng)了
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(aviewAction)];
[self addGestureRecognizer:tap];
}
return self;
}
- (void)cviewAction {
NSLog(@"單擊傳遞到C");
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
return self ;
}
hit:withEvent:方法底層會(huì)調(diào)用pointInside:withEvent:方法判斷點(diǎn)在不在方法調(diào)用者的坐標(biāo)系上。因?yàn)橹貙懥嗣渚詐ointInside就沒調(diào)用了暇屋。
pointInside:withEvent:方法判斷點(diǎn)在不在當(dāng)前view上(方法調(diào)用者的坐標(biāo)系上)如果返回YES,代表點(diǎn)在方法調(diào)用者的坐標(biāo)系上;返回NO代表點(diǎn)不在方法調(diào)用者的坐標(biāo)系上洞辣,那么方法調(diào)用者也就不能處理事件咐刨。
事件的傳遞和響應(yīng)的區(qū)別:
事件的傳遞是從上到下(父控件到子控件),事件的響應(yīng)是從下到上(順著響應(yīng)者鏈條向上傳遞:子控件到父控件扬霜。
手勢(shì)相關(guān)
1.如果一個(gè)手勢(shì)A的識(shí)別部分是另一個(gè)手勢(shì)B的子部分時(shí)定鸟,默認(rèn)情況下A就會(huì)先識(shí)別,B就無法識(shí)別
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
2.使多個(gè)手勢(shì)同時(shí)生效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
3.父視圖和子視圖都有手勢(shì)的時(shí)候著瓶,子視圖會(huì)出現(xiàn)無法響應(yīng)的情況
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UITableView class]]) {
return NO;
}
if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {
return NO;
}
return YES;
}
4.UIControl和手勢(shì)同時(shí)存在联予,則會(huì)按照響應(yīng)鏈,先響應(yīng)單擊事件