標籤:style blog class code tar http
iOS手勢有著如下幾種:
- UITapGestureRecognizer
- UIPinchGestureRecognizer
- UIRotationGestureRecognizer
- UISwipeGestureRecognizer
- UIPanGestureRecognizer
- UILongPressGestureRecognizer
上面的手勢對應的操作是:
- Tap (點一下)
- Pinch (二指往內或往撥出動,平時經常用到的縮放) 矩陣變換
- Rotation (旋轉) 矩陣變換
- Swipe (滑動,快速移動)
- Pan (拖移,慢速移動) 矩陣變換
- LongPress (長按)
注意:以下樣本均把手勢封裝進一個View當中
UITapGestureRecognizer - 點選手勢
GestureView.h + GestureView.m
GestureView.h GestureView.m
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
Attaching a gesture recognizer to a view defines the scope of the represented gesture, causing it to receive touches hit-tested to that view and all of its subviews. The view establishes a strong reference to the gesture recognizer.
將手勢辨識器附著在一個view上,實際上定義了一個手勢接收的地區,會將接收到的觸摸事件傳遞給這個view以及這個view的所有的subviews.這個view會對這個手勢辨識器強引用.
可以總結兩點:
1. 手勢會傳遞給這個view中所有的subviews
2. view會強引用手勢辨識器
使用如下:
點選手勢有兩個參數可以設定:
numberOfTapsRequired 點擊幾次觸發事件(預設是1)
numberOfTouchesRequired 需要幾個手指點擊(預設是1)
UIPinchGestureRecognizer - 縮放
GestureView.h + GestureView.m
GestureView.h GestureView.m
縮放手勢會用到矩陣變換.
UIRotationGestureRecognizer - 旋轉
GestureView.h + GestureView.m
GestureView.h GestureView.m
UISwipeGestureRecognizer - 滑動
GestureView.h + GestureView.m
GestureView.h GestureView.m
UIPanGestureRecognizer - 平移
GestureView.h + GestureView.m
GestureView.h GestureView.m
UILongPressGestureRecognizer - 長按手勢
GestureView.h + GestureView.m
GestureView.h GestureView.m
問題:如何處理一個view中添加了兩個手勢,1個是單擊的手勢,一個是雙擊的手勢呢?
可以使用這個方法requireGestureRecognizerToFail:
GestureView.m
實際上,這種方式會有延時感-_-!!!!
問題:如何將長按手勢和拖拽手勢合并在一起呢?
我們需要用代理實現,實現以下的方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Asks the delegate if two gesture recognizers should be allowed to recognize gestures simultaneously.
詢問這個代理,是否允許兩個手勢同時觸發.
GestureView.m
根據手勢狀態來識別手勢觸發事件的全稱細節是十分重要的.
問題:如何讓一個view的部分地區響應拖拽事件呢?
比方說,我們只需要下面紅色線指定的地區響應拖拽事件:
GestureView.m
要實現那個效果,以下方法是核心方法,配合手勢的狀態使用:
// 擷取到當前手勢在當前視圖座標中觸摸的點
CGPoint point = [sender locationInView:self];
問題:如何在ViewController中擷取到點擊的座標,讓一個view跟隨觸摸點移動呢?
可以使用這幾個最原始的處理觸摸事件的方法來達到效果.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
RootViewController.m
也可以直接使用拖拽手勢來實現的,不過不完美
RootViewController.m
他們兩者的對比關係:
手勢處理中核心的地方:
1. UIGestureRecognizerState非常重要,觸發事件時可以直接根據這個狀態值來判斷事件的發生順序
2. 處理多手勢衝突時,可以使用依賴requireGestureRecognizerToFail:來處理,但效果不好
3. 處理多個手勢並發響應的時候,需要實現代理並執行方法,請參考上面的案例
4. 僅僅處理一個view上局部的手勢事件,需要用到手勢的locationInView:方法,並與UIGestureRecognizerState狀態值配合使用
附錄:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
這是手勢的代理方法,在可以不移除手勢的情況下關閉手勢的響應,此方法涉及到響應鏈.