iOS基礎 - 觸摸事件與手勢識別

1、iOS的輸入事件

UIKit可識別三種類型的輸入事件:程序員

觸摸事件app

運動(加速計)事件ide

遠程控制事件函數

2、UIEvent

iOS中許多事件對象都是UIEvent類的實例,記錄事件產生的時刻和類型性能

UIEvent類事件類型的enum常量:spa

typedef NS_ENUM(NSInteger, UIEventType) {對象

    UIEventTypeTouches,繼承

    UIEventTypeMotion,遞歸

    UIEventTypeRemoteControl,隊列

};

UIEvent對象的type屬性能夠獲取事件的類型

3、響應者對象

iOS中不是任何對象都能處理事件,只有繼承了UIResponder的對象才能接收並處理事件。咱們稱之爲「響應者對象」

UIApplicationUIViewControllerUIView都繼承自UIResponder,所以它們都是響應者對象,都可以接收並處理事件

4、觸摸事件的處理

UIViewUIResponder的子類,能夠覆蓋下列4個方法處理不一樣的觸摸事件。

1. 一根或者多根手指開始觸摸屏幕

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

2.一根或者多根手指在屏幕上移動(隨着手指的移動,會持續調用該方法)

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

3.一根或者多根手指離開屏幕

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

4.觸摸結束前,某個系統事件(例如電話呼入)會打斷觸摸過程

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

注意:全部UIKit控件均繼承自UIView

上述4個方法都有個UIEvent的參數,經過UIEvent能夠獲得事件的類型和產生時間,以及當前處於活動狀態的全部觸摸操做。可是,一般會使用UITouch對象而不是UIEvent對象來處理觸摸事件

當用戶觸摸屏幕時,系統會建立一個UITouch實例,並將該對象和接觸屏幕的那根手指關聯。UITouch保存着手指在屏幕上觸摸的位置。當手指移動時,系統會更新同一個UITouch對象,使之可以一直保存該手指在屏幕上的當前位置。當手指離開屏幕時,系統會取消相應的UITouch對象

UITouch對象還會保存一些其餘信息,好比,手指的前一個位置、手指按下屏幕的次數(tapCount, 能夠用來判斷單擊和雙擊事件)

提示:iPhone開發中,要避免使用雙擊事件!

5、UITouch類中包含五個屬性

window:觸摸產生時所處的窗口。因爲窗口可能發生變化,當前所在的窗口不必定是最開始的窗口

view:觸摸產生時所處的視圖。因爲視圖可能發生變化,當前視圖也不必定時最初的視圖

tapCount:點按操做和鼠標的單擊操做相似,tapCount表示短期內點按屏幕的次數。所以能夠根據tapCount判斷單擊、雙擊或更多的點按

timestamp:時間戳記錄了觸摸事件產生或變化時的時間,單位是秒

phase:觸摸事件在屏幕上有一個週期,即觸摸開始、觸摸點移動、觸摸結束,還有中途取消。經過phase能夠查看當前觸摸事件在一個週期中所處的狀態。phaseUITouchPhase類型的,是一個枚舉配型,包含:

UITouchPhaseBegan(觸摸開始)

UITouchPhaseMoved(接觸點移動)

UITouchPhaseStationary(接觸點無移動)

UITouchPhaseEnded(觸摸結束)

UITouchPhaseCancelled(觸摸取消)

6、UITouch類中包含兩個成員函數:

- (CGPoint)locationInView:(UIView *)view

返回一個CGPoint類型的值,表示觸摸在view這個視圖上的位置,這裏返回的位置是針對view的座標系的。調用時傳入的view參數爲空的話,返回的時觸摸點在整個窗口的位置

- (CGPoint)previousLocationInView:(UIView *)view

該方法記錄了前一個座標值,函數返回也是一個CGPoint類型的值, 表示觸摸在view這個視圖上的位置,這裏返回的位置是針對view的座標系的。調用時傳入的view參數爲空的話,返回的時觸摸點在整個窗口的位置

7、觸摸事件的處理

當某個UIView發生觸摸事件時,系統會將和事件相關的UITouch對象做爲參數傳入

由於能夠有多根手指同時觸發同一個事件,因此傳給視圖的是一組UITouch對象,保存在NSSet中,例如:

若是兩根手指同時觸摸某個視圖,那麼touchesBegan:withEvent:的第一個參數是包含兩個UITouch實例的NSSet對象

若是這兩根手指一前一後分開觸摸同一個視圖,那麼視圖會收到兩個獨立的touchesBegan:withEvent:消息,而且每一個NSSet對象中只包含一個UITouch對象

所以,根據NSSetUITouch的個數能夠判斷出是單點觸摸仍是多點觸摸

8、觸摸事件的傳遞

發生觸摸事件後,系統會將該事件加入到一個由UIApplication管理的事件隊列中

UIApplication會從事件隊列中取出最前面的事件並將其分發以便處理,一般,先發送事件給應用程序的主窗口

主窗口會調用hitTest:withEvent:方法在視圖繼承樹中找到一個最合適的子視圖來處理觸摸事件,該子視圖即爲hit-test視圖

若是hit-test視圖不處理收到的事件消息,UIKit則將事件轉發到響應者鏈中的下一個響應者,看其是否能對該消息進行處理

9、響應者鏈

響應者鏈條,是經過遞歸構成的一組UIResponder對象的鏈式序列!

10、響應者鏈事件處理過程

若是hit-test視圖沒法處理事件,則經過響應者鏈向上傳遞

若是hit-test視圖的控制器存在,就傳遞給控制器;若是控制器不存在,則將其傳遞給它的父視圖

若是視圖或它的控制器沒法處理收到的事件或消息,則將其傳遞給該視圖的父視圖

每個在視圖繼承樹中的上層視圖若是不能處理收到的事件或消息,則重複上面的步驟

在視圖層次結構的最頂級視圖,若是也不能處理收到的事件或消息,則其將事件或消息傳遞給window對象進行處理

若是window對象也不處理,則其將事件或消息傳遞給UIApplication對象

若是UIApplication也不能處理該事件或消息,則將其丟棄

11、UIView不接收處理事件的三種狀況

不接收用戶交互:

userInteractionEnabled = NO;

隱藏:

hidden = YES;

透明:

alpha = 0~0.01

12、觸摸事件小結

四個UITouch事件:

1. 一根或者多根手指開始觸摸屏幕

- (void)touchesBegan:withEvent:

2.一根或者多根手指在屏幕上移動

- (void)touchesMoved:withEvent:

3.一根或者多根手指離開屏幕

- (void)touchesEnded:withEvent:

4.觸摸結束前,某些系統事件會打斷觸摸過程

- (void)touchesCancelled:withEvent:

按照響應者鏈順序遞歸查找最早處理事件的UIView,重寫hitTest:withEvent:方法能夠攔截觸摸事件

觸摸事件處理簡單觸摸很是容易,可是要處理複雜的手勢就會變得比較很是困難。爲了解決這一問題,蘋果推出了手勢識別,在簡化手勢處理的同時,還有效地統一了用戶使用習慣

十3、手勢識別——Gesture Recognizer

iOS3.2版本以後,蘋果推出了手勢識別(Gesture Recognizer),其目的是:

簡化開發者的開發難度

統一用戶體驗

iOS目前支持的手勢識別

UITapGestureRecognizer(點按)

UIPinchGestureRecognizer(捏合)

UIPanGestureRecognizer(拖動)

UISwipeGestureRecognizer(輕掃)

UIRotationGestureRecognizer(旋轉)

UILongPressGestureRecognizer(長按)

提示:目前遊戲中的手勢識別使用的很少

十4、手勢識別的狀態

typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {

    // 沒有觸摸事件發生,全部手勢識別的默認狀態

    UIGestureRecognizerStatePossible,

    // 一個手勢已經開始但還沒有改變或者完成時

    UIGestureRecognizerStateBegan,

    // 手勢狀態改變

    UIGestureRecognizerStateChanged,

    // 手勢完成

    UIGestureRecognizerStateEnded,

    // 手勢取消,恢復至Possible狀態

    UIGestureRecognizerStateCancelled, 

    // 手勢失敗,恢復至Possible狀態

    UIGestureRecognizerStateFailed,

    // 識別到手勢識別

    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded

};

提示:UITapGestureRecognizer也被稱爲離散手勢,該手勢識別不會被取消,只是調用一次selector任務

十5、手勢識別的使用方法

建立手勢識別實例

設置手勢識別屬性,例如手指數量,方向等

將手勢識別附加到指定的視圖之上

編寫手勢觸發監聽方法

十6、手勢識別的屬性

state——手勢狀態

view——手勢發生視圖

經常使用方法

locationInView 得到手勢發生對應視圖所在位置

translationInView 相對於起始位置在視圖中的平移位置

十7、搖晃監聽——使用方法

重寫canBecomeFirstResponder方法返回YES,容許視圖控制器成爲第一響應者

viewDidAppear方法中將視圖控制器設置爲第一響應者

viewDidDisappear方法中註銷視圖控制器第一響應者的身份

監聽並處理運動事件監聽方法

十8、 觸摸事件操做

 觸摸事件的類型一共有四個,一次完整的觸摸,至少包括開始和結束兩個事件

 1> 觸摸開始,用手指(一根或者多根)按在屏幕上

 2> 觸摸移動,手指在屏幕上發生移動(有可能會發生)

 3> 觸摸結束,手指從屏幕上離開

 4> 觸摸被取消,由於系統事件(例如電話呼叫)一次觸摸事件被取消

 觸摸對象UITouch的屬性及方法

 屬性:

 1> view:       檢測到觸摸事件的視圖,在開發中使用最爲頻繁的屬性

 2> window:     窗口,發生觸摸事件的窗口

 3> phase:      相位屬性,開發中極少使用,通常用戶自定義手勢識別

 4> timestamp:  發生觸摸的時間

    以上兩個屬性,一般用戶開發自定義手勢識別,平常開發中不須要使用。

 5> tapCount:   發生觸摸時,在短期內,手指點按的次數,一般用於判斷單擊仍是雙擊

    提示:在iOS開發中,儘可能少用雙擊事件!

    若是要使用雙擊,須要有圖形化的界面提示用戶,某一個控件上是容許雙擊操做的。

 方法:

 1> locationInView:             發生觸摸事件相對視圖的位置(座標點)

 2> previousLocationInView:     發生觸摸事件前一次手指所在的位置(座標點)

 對於單點觸摸,常用

    UITouch *touch = [touches anyObject];

    從touches集合中獲取到用戶的觸摸對象

    一般,在應用程序開發中,爲了簡化程序的複雜度,通常只是用單點觸摸,

    而若是須要支持多點觸摸,一般是使用手勢識別來處理。

十9、 多點觸摸事件操做

 1. 若是是一根手指,在屏幕上繪製藍色的圖像

 2. 若是是多根手指,一根手指是藍色的圖像,另一根是紅色圖像

 1> touchesMoved方法中,touches集合中的UITouch對象的順序不會發生改變

 2> 在使用塊代碼時,其中的代碼只是預先準備好的一個程序塊,在須要時會被調用

二10、 hitTest

用於檢測具體響應用戶觸摸點視圖的方法

     - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

    與

    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

    在視圖內部返回YES,不然返回NO

     聯合使用來判斷用戶觸摸點的位置是否在指定的視圖內部,若是是,表示該視圖能夠接收用戶交互。

     以上兩個方法會被循環遞歸,屢次調用!直至找到最適合響應用戶請求的視圖!

     提示:通常狀況下,不要輕易重寫這兩個方法,由於一旦方法內部使用了消耗量大的代碼,會嚴重影響系統的性能!

    1) 若是返回nil,表示沒有響應的視圖

    2) 若是返回視圖,表示該視圖接收用戶的響應

 接收用戶觸摸響應的幾個條件

    1) self.userInteractionEnabled = YES;   容許接收用戶響應

    2) self.hidden = NO;                    只有現實的視圖才能接收用戶觸摸

    3) self.alpha > 0.01;                   視圖的透明度必定要可見

     提示:並非全部的控件都默認接收用戶交互的,譬如:UIImageViewUILabel

 參數說明

    point   用戶觸摸的點,相對於當前視圖座標系的座標點

  event   用戶觸摸事件,開發中通常程序員不使用,該事件用於在響應者鏈條上傳遞

相關文章
相關標籤/搜索