轉載的這個部落格,詳細見這個部落格 www.jianshu.com/p/2e074db79…
重點
1.UIView不能接收觸控事件的三種情況:
-
不允許互動:userInteractionEnabled = NO (UIimageView)
-
隱藏:如果把父控制元件隱藏,那麼子控制元件也會隱藏,隱藏的控制元件不能接受事件
-
透明度:如果設定一個控制元件的透明度<0.01,會直接影響子控制元件的透明度。alpha:0.0~0.01為透明。
2.父控制元件不能接收觸控事件,子控制元件也不能接受事件
3.如何尋找最合適的view應用如何找到最合適的控制元件來處理事件?
- 首先判斷主視窗(keyWindow)自己是否能接受觸控事件
- 觸控點是否在自己身上
- 從後往前遍歷子控制元件,重複前面的兩個步驟(首先查詢陣列中最後一個元素)
- 如果沒有符合條件的子控制元件,那麼就認為自己最合適處理
程式碼的分析
// 作用:尋找並返回最合適的view
// UIApplication -> [UIWindow hitTest:withEvent:]尋找最合適的view告訴系統
// point:當前手指觸控的點
// point:是方法呼叫者座標系上的點
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
// 1.判斷下視窗能否接收事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
// 2.判斷下點在不在視窗上
// 不在視窗上
if ([self pointInside:point withEvent:event] == NO) return nil;
// 3.從後往前遍歷子控制元件陣列
//重點
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0; i--) {
// 獲取子控制元件
UIView *childView = self.subviews[i];
// 座標系的轉換,把視窗上的點轉換為子控制元件上的點
// 把自己控制元件上的點轉換成子控制元件上的點
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) {
// 如果能找到最合適的view
return fitView;
}
}
// 4.沒有找到更合適的view,也就是沒有比自己更合適的view
return self;
}
// 作用:判斷下傳入過來的點在不在方法呼叫者的座標系上
// point:是方法呼叫者座標系上的點
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return NO;
}複製程式碼