當一個控件不能接收時間時通常有如下幾種狀況
1.不接收用戶交互userInteractionEnabled = NO
2.當一個控件隱藏時Hidden = YES
3.當一個控件爲透明白時ide
注意:UIImageView
以及它的子控件默認是不能接收觸摸事件的spa
用戶點擊屏幕產生的一個觸摸事件,通過一系列的傳遞過程後,會找到一個最適合的視圖來處理事件.找到最合適的視圖控件後,就會調用控件的touches
方法來做具體的時間處理.touches
的默認作法是將事件順着響應者鏈條向上傳遞,將事件交給上一個響應者處理code
UIResponder
的對象1.先判斷本身是否能接收觸摸事件
2.再判斷觸摸的當前點在不在本身身上
3.若是在本身身上,它會從後往前遍歷子控件,遍歷出每個控件後,重啓前兩步
4.若是沒有符合條件的子控件,那麼自身就是最合適的View對象
在尋找最合適View的過程當中,系統會調用2個方法blog
1 //做用:尋找最適合的View 2 //何時調用:當事件傳遞給當前View時就會調用這個方法 3 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ 4 UIView *fitView = [super hitTest:point withEvent:event]; 5 NSLog(@"%@",fitView); 6 return fitView; 7 } 8 //做用:判斷觸摸點在不在當前的View上. 9 //何時調用:在hitTest方法當中會自動調用這個方法. 10 //注意:point必須得要跟當前View同一個座標系. 11 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{ 12 return YES; 13 }
那麼方法底層是如何實現的呢?hitTest: withEvent:
1 // 判斷本身可否接收事件 2 if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01){ 3 return nil; 4 } 5 // 觸摸點在不在本身身上 6 if ([self pointInside:point withEvent:event] == NO) { 7 return nil; 8 } 9 // 從後往前遍歷本身的子控件(重複前面的兩個步驟) 10 int count = (int)self.subviews.count; 11 for (int i = count -1; i >= 0; i--) { 12 UIView *childV = self.subviews[i]; 13 // point必須得要跟childV相同的座標系. 14 // 把point轉換childV座標系上面的點 15 CGPoint childP = [self convertPoint:point toView:childV]; 16 UIView *fitView = [childV hitTest:childP withEvent:event]; 17 if (fitView) { 18 return fitView; 19 } 20 } 21 // 若是沒有符合條件的子控件,那麼就本身最適合處理 22 return self;
在開發中或多或少會須要一些特殊的點擊,這裏有2個小例子供你們參考繼承
1 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ 2 3 //當觸摸點在按鈕上的時候,才讓按鈕去響應事件. 4 //把當前點轉換成按鈕座標系上的點. 5 CGPoint btnP = [self convertPoint:point toView:self.btn]; 6 if ( [self.btn pointInside:btnP withEvent:event]) { 7 return self.btn; 8 }else{ 9 return [super hitTest:point withEvent:event]; 10 } 11 }