在iOS學習23之事件處理中,小編詳細的介紹了事件處理,在這裡小編敘述一下它的相關原理 1、UITouch對象 在觸摸事件的處理方法中都會有一個存放著UITouch對象的集合,這個參數有什麼用呢? (1)UITouch 對象的簡介 當用戶用一根手指觸摸屏幕時,會創建一個與手指相關聯的 UITouch ...
在iOS學習23之事件處理中,小編詳細的介紹了事件處理,在這裡小編敘述一下它的相關原理
1、UITouch對象
在觸摸事件的處理方法中都會有一個存放著UITouch對象的集合,這個參數有什麼用呢?
(1)UITouch 對象的簡介
-
當用戶用一根手指觸摸屏幕時,會創建一個與手指相關聯的 UITouch 對象
-
一根手指對應一個 UITouch 對象
-
UITouch 的作用
保存著根手指相關的信息,比如觸摸的位置、時間、階段
-
當手指移動時,系統會更新同一個 UITouch 對象,使之能夠一直保持該手指在的觸摸位置
-
當手指離開屏幕時,系統會銷毀相應的 UITouch 對象
提示:iPhone 開發中,要避免使用雙擊事件!
(2)UITouch 的屬性
- 觸摸產生時所產生的視窗
@property (nonatomic, readonly, retain) UIWindow *window;
- 觸摸產生時所產生的視圖
@property (nonatomic, readonly, retain) UIView *view;
- 短時間內點按屏幕的次數,可以根據 tapCount 判斷單擊、雙擊或更多的點擊
@property (nonatomic, readonly) NSUInteger tapCount;
- 記錄了觸摸事件產生或變化時的時間,單位是秒
@property (nonatomic, readonly) NSTimeInterval timestamp;
- 當前觸摸事件所處的狀態
@property (nonatomic, readonly) UITouchPhase phase;
(3)UITouch 的方法
// 返回值表示觸摸在View上的位置 - (CGPoint)locationInView:(UIView *)view; // 該方法記錄了前一個觸摸點的位置 - (CGPoint)previousLocationInView:(UIView *)view;
-
方法一中返回的位置針對View的坐標系(以View的左上角為原點(0,0))
-
當方法一調用時傳入的View參數為 nil 的話,返回的是觸摸點在 UIWindow 的位置
實例代碼:
// 當手指在view上移動的時候 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"%s",__func__); // 獲取UITouch對象 UITouch *touch = [touches anyObject]; // 獲取當前點 CGPoint curP = [touch locationInView:self]; // 獲取上一個點 CGPoint preP = [touch previousLocationInView:self]; // 獲取x軸偏移量 CGFloat offsetX = curP.x - preP.x; // 獲取y軸偏移量 CGFloat offsetY = curP.y - preP.y; // 修改view的位置(frame,center,transform) self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY); // self.transform = CGAffineTransformMakeTranslation(offsetX, 0); }
預設不支持多個手指,要修改 Multiple Touch 屬性,在 storyboard 中將這個屬性打鉤就可以
2、原理
(1)事件的產生和傳遞
-
發生觸摸事件後,系統會將該事件加入到一個由 UIApplication 管理的事件隊列中
-
UIApplication 會從事件隊列中取出最前面的事件,並將事件分發下去以便處理,通常,先發送事件給應用程式的主視窗(keyWindow)
-
主視窗會在視圖層次結構中找到一個最適合的視圖來處理觸摸事件,這也是整個事件處理過程的第一步
-
找到合適的視圖控制項後,就會調用視圖控制項的 touches 方法來做具體的事件處理
touchesBegan...
touchesMoved...
touchesEnded...
(2)UIView不接收觸摸事件的三種情況
- 用戶交互關閉
userInteractionEnabled = NO;
- 視圖隱藏
hidden = YES;
- 透明
alpha = 0.0 ~ 0.1
(3)如何找到最適合的控制項
- 判斷自己是否能接收觸摸事件,底層實現方法:hitTest: withEvent:
// 作用:就是用來尋找最合適的view // 什麼時候調用:當事件傳遞給控制項的時候,就會調用控制項的這個方法,去尋找最合適的view // point:當前的觸摸點,point這個點的坐標系就是方法調用者 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { // 調用系統的做法去尋找最合適的view,返回最合適的view UIView *fitView = [super hitTest:point withEvent:event]; return fitView; }
該方法的返回值就是事件處理的視圖控制項
當該方法在 UIWindow 類中重寫,要使下圖無論點哪裡都是最底下白色的視圖進行處理,就返回 self.subviews[0]。
- 判斷觸摸點是否在自己身上,底層實現方法:pointInside: withEvent:
// 作用:判斷當前這個點在不在方法調用者(控制項)上 // 在判斷是否是最適合的控制項的時候調用 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { return YES; }
- 從後往前遍歷子控制項,重覆前面的兩個步驟