iOS響應(yīng)鏈和手勢總結(jié)

繼承關(guān)系

image.png

UIResponder 繼承關(guān)系圖
只有繼承了UIResponder的對象才能接受并處理事件

事件傳遞

UIView是UIResponder的子類,可以覆蓋下列4個方法處理不同的觸摸事件

// 一根或者多根手指開始觸摸view,系統(tǒng)會自動調(diào)用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
// 一根或者多根手指在view上移動,系統(tǒng)會自動調(diào)用view的下面方法(隨著手指的移動,會持續(xù)調(diào)用該方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
// 一根或者多根手指離開view,系統(tǒng)會自動調(diào)用view的下面方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
// 觸摸結(jié)束前,某個系統(tǒng)事件(例如電話呼入)會打斷觸摸過程,系統(tǒng)會自動調(diào)用view的下面方法
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
// 提示:touches中存放的都是UITouch對象

觸摸事件的傳遞是從父控件傳遞到子控件,遍歷子視圖的時候從后到前
也就是UIApplication->window->尋找處理事件最合適的view

判斷條件是

  • 1.自身是否能夠響應(yīng)觸摸事件
  • 2.觸摸點在不在自己身上
  • 3.1 如果在則遍歷子視圖,尋找最合適的
  • 3.2 如果沒有子視圖,且找不到最合適的,則自身成為最合適的響應(yīng)者
    然后該類響應(yīng)touchs方法

事件攔截

如果觸摸點不在自身上則不去遍歷子視圖
如果在則一定會去遍歷所有子視圖,所以說不管子視圖有沒有這個點,只要父視圖有,則會默認(rèn)被遍歷一遍。
第一層的子視圖都會調(diào)用hitTest:withEvent:方法

所以只要在hitTest:withEvent:中返回哪個View,哪個View就是響應(yīng)者。
例如:點擊父視圖,子視圖重寫hitTest:withEvent:,返回self這樣就達(dá)到了擴(kuò)大子視圖響應(yīng)范圍的效果

image.png

如上圖,在橙色的圖上點擊,由于藍(lán)色是第一層子視圖,所以藍(lán)色會被事件傳遞一次,調(diào)用了hitTest
在藍(lán)色類C中創(chuàng)建一個手勢方法,并重寫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:方法底層會調(diào)用pointInside:withEvent:方法判斷點在不在方法調(diào)用者的坐標(biāo)系上。因為重寫了,所以pointInside就沒調(diào)用了。
pointInside:withEvent:方法判斷點在不在當(dāng)前view上(方法調(diào)用者的坐標(biāo)系上)如果返回YES,代表點在方法調(diào)用者的坐標(biāo)系上;返回NO代表點不在方法調(diào)用者的坐標(biāo)系上,那么方法調(diào)用者也就不能處理事件。

事件的傳遞和響應(yīng)的區(qū)別:
事件的傳遞是從上到下(父控件到子控件),事件的響應(yīng)是從下到上(順著響應(yīng)者鏈條向上傳遞:子控件到父控件。

手勢相關(guān)

1.如果一個手勢A的識別部分是另一個手勢B的子部分時,默認(rèn)情況下A就會先識別,B就無法識別

- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;

2.使多個手勢同時生效

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

3.父視圖和子視圖都有手勢的時候,子視圖會出現(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和手勢同時存在,則會按照響應(yīng)鏈,先響應(yīng)單擊事件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容