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

來源:互聯網
上載者:User

事件處理指南(Event Handling Guide for 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 方法來重設內部狀態

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.