你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 事件處理指南(Event Handling Guide for iOS) 閱讀筆記 (一) 手勢識別

事件處理指南(Event Handling Guide for iOS) 閱讀筆記 (一) 手勢識別

編輯:IOS開發綜合

 

Gesture Recognizers 手勢識別

 


 

總覽:

1. 應用可以從用戶觸摸VIew得到事件.

2. 應用可以從用戶移動設備得到事件.

3. 應用可以從用戶操作多媒體得到遠程控制事件(比如從耳機控制音量)

Gesture Recognizers 手勢識別

手勢識別是從低級別的事件通過代碼轉換為高級事件, 當你對一個視圖觸摸控制的時候,手勢識別就會識別判斷是哪一種操作, 比如 swipe, pinch, 或者 rotation.如果這個操作被識別了, 手勢器會向target發送消息. Target 通常是一個控制器.

\

使用系統內置的手勢識別器比較方便, 你也可以自定義識別器, 會在下面說到.系統識別器如圖:

\

 

手勢識別器是綁定在一個視圖上的, 一個視圖也可以由多個手勢識別器.

手勢可分為獨立和持續,比如 tap 是獨立事件, pinching 捏合 就是持續事件, 手勢識別器負責在識別到手勢後發送消息給target

\

 

創建系統手勢識別器需要三步驟:

1. 創建識別器實例, 包括指定target, action, 特殊屬性, 如numberOfTapsRequired

2. 將識別器綁定到視圖上

3. 實現action的方法並處理事件

 

手勢識別工作方式

他的識別順序有一系列的狀態決定.狀態說明定義在 UIGestureRecognizerState 枚舉中. 從一個狀態到另一個狀態是不定的, 取決於當前的情況.下圖說明了 獨立事件和持續事件的狀態轉換:

\

一旦狀態到 Recognied 識別器會發送消息給target, 持續時間會多次發送改變的消息給target

 

手勢互動

一個視圖上可以有多個手勢識別器, 查看這些識別器可以在視圖的屬性 gestureRecognizers 中查看, 也可以通過 addGestureRecognizer: and removeGestureRecognizer: 添加和移除手勢識別器. 通常, 一個視圖上的多個手勢被識別是無序的,每次識別可能順序都不一樣,你可以通過 UIGestureRecognizer 類的方法, 代理方法 或繼承來實現這些行為:

1. 指定一個識別器在另一個識別器之前被識別到.

2. 允許兩個識別器同時工作

3. 阻止一個識別器工作

你也可以定義兩個手勢識別器觸發順序, 通過UIGestureRecognizer 類方法處理

 

- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer; // 直到另一個手勢失敗的時候才處理本手勢

 

阻止手勢識別 使用手勢代理方法處理 UIGestureRecognizerDelegate

 

這兩個代理方法都可以達到阻止手勢的目的

 

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

當觸摸開始,並且你能立即判斷哪個手勢是否需要開始, 可以使用gestureRecognizer:shouldReceiveTouch: 代理方法, 每次有新的觸摸都會調用該方法

如果需要等待足夠長時間才能判斷哪個手勢是否開始,可以使用gestureRecognizerShouldBegin: 代理方法, 該方法是在識別器將要從狀態 possible 轉換至下一個狀態是調用.

 

允許兩個手勢同時被識別

默認兩個識別器不能再同一時刻被識別,但是,假設你想使用放大和旋轉同時進行,就需要進行配置了.可以使用代理方法

gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 來設置.

 

與其他界面控制控件交互

在iOS6及以後,默認的系統控制控件的手勢不能被覆蓋.比如,默認UIButton的點擊事件是一個 single tap , 如果你有自己定義的一個 single tap 手勢與UIButton 綁定,點擊button後 button的action 方法會調用, 而不是single tap 手勢觸發.類似的還有很多, 比如在UISlider 上添加 swip 手勢, 在UISwitch 上添加 pan 手勢. 當然, 也可以繼承系統組件來更改事件響應.

 

一個事件包含了所有當前多點觸摸的一個序列, 一個手勢可以有一個或多個用 UITouch 對象代表的觸摸.比如: 一個捏合關閉的手勢包含了兩個觸摸--兩個手指在屏幕上向相反方向滑動. 一個多點觸摸是由 從手指接觸到屏幕開始, 到最後一個手指離開屏幕後之間的時間組成的序列. 當手指在屏幕上移動的時候, 系統會發送 用UITouch對象代表的事件, 多點觸摸時間由 UITouch 的 type UIEventTypeTouches 代表. 每一個UITouch 對象只能追蹤一個單一手指的活動, 在手指滑動中, UIKit 會更新UITouch的屬性,這些屬性包括 觸摸的階段, 在觸摸View上的位置, 它之前的位置和時間戳.

 

一個觸摸的階段標志的觸摸何時開始, 何時移動或靜止, 何時結束, 下圖為觸摸的階段圖

\

 

當有觸摸改變時候, 系統會調用下面的方法通知應用

● touchesBegan:withEvent: method when one or more fingers touch down on the screen.
● touchesMoved:withEvent: method when one or more fingers move.
● touchesEnded:withEvent: method when one or more fingers lift up from the screen.

● touchesCancelled:withEvent: method when the touch sequence is canceled by a system event, such as an incoming phone call.

每個方法都和一個觸摸階段關聯

 

調整UITouch在UIView 之間的傳遞及響應

可能有許多時候你需要一個View 在手勢識別器識別之前 接收到Touch 事件, 但是當你在更改Touch傳遞順序之前, 最好了解一下系統默認的操作行為.

默認觸摸事件從 UIApplication 傳遞到UIWindow對象, UIWindow 將事件發送至任何一個綁定在被觸摸到的View上的手勢識別器.

UIWindow 會延遲touch對象到View去, 這樣可以在這段延遲期間識別器可以識別手勢,如果手勢被識別到, 那麼UIWindow將不會傳遞任何touch對象到這個view 上了. 並且取消之前發送到這個view上的touch序列.

 

假設有一個不連續的手勢需要兩個手指觸摸,這將會轉化成兩個分開的touch對象,當觸摸開始, touch對象從應用傳到window裡的view

這個 touch消息傳遞的序列如下:

\

1. window 在began 階段發出兩個touch對象 - 通過touchesBegan:withEvent: 方法去識別, 識別器此時還沒有識別, 所以 狀態為 Possible. window發送這些消息給綁定手勢觸發器的view.

2.window 在 move 階段發出兩個touch 對象- 通過touchesMoved:withEvent: 方法去識別, 識別器仍然沒有識別到, 所以狀態為 Possible.消息會傳到view.

3.window 在ended 階段 發出一個touch 對象 - 通過touchesEnded:withEvent: 方法去識別, 識別器沒有因不足的信息而放棄, 但是消息不會傳到view上了.

4.window在ended 階段 發出了另一個touch對象, 這時候觸發器觸發了,找到了手勢, 所以狀態改為 recognized . view調用touchesCancelled:withEvent: 方法取消前一個touch對象觸發方法, 這兩個touch對象最終階段為 canceled.

 

影響touch對象傳遞到view

你可以改變幾個UIGestureRecognizer 類的屬性值, 從而改變默認的touch傳遞路徑,如果你改變了以下屬性的默認值, 你將得到不同的行為:

 

屬性 @property(nonatomic)BOOL delaysTouchesBegan; 默認為NO -- 通常,window 在began 和move 階段發送touch對象到view上, 如果設置delaysTouchesBegan 為YES, 它將會阻止屬性 @property(nonatomic)BOOL delaysTouchesEnded; 默認為YES -- 當設置為YES的時候, 它確保當手勢取消後, view不會響應事件, 當識別器在識別過程中, window不會傳遞事件對象給綁定的view.如果識別器識別到手勢,它將取消touch事件, 如果沒有識別到手勢, 將會觸發 -touchedEnded:withEvent 方法. 如果設置NO, 就允許了識別touch時間和手勢同時觸發. 舉個例子: 一個view綁定了 tap 手勢, 並且需要2次點擊. 當我們雙擊的時候, 如果設置為YES, 觸發方法順序為 1. touchesBegin:withEvent: 2. touchedBegin:withEvent 3.touchesCancelled:withEvent 4.touchesCancelled:withEvent: 如果設置了NO, 觸發方法順序為: 1. touchesBegin:withEvent: 2.touchesEnded:withEvent: 3.touchesBegin:withEvent: 4.touchedCancelled:withEvent. 創建自定義的手勢識別器
首先創建一個UIGestureRecognizer 的子類, 然後引入頭文件 #import, 實現下面的方法, 必須首先調用父類super 方法,即使是空實現
- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
而且還注意到 UIGestureRecognizerSubclass 頭文件中的 state 屬性變為 readwrite 可讀寫的,而不是原來的只讀的了

 

重置手勢識別器的狀態 state

當我們的識別器的識別狀態改變(UIGestureRecognizerState)時並且阻止了繼續識別的時候,識別器會調用 -reset 方法來重置內部狀態

 

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved