iOS UIGestureRecognizer (手勢的基本知識介紹)

手勢識別在 iOS 中非常重要,他極大地提高了移動設備的使用便捷性。iOS 系統在 3.2 以後,他提供了一些常用的手勢(UIGestureRecognizer 的子類),開發者可以直接使用他們進行手勢操作。
手勢類型(他們都繼承自UIGestureRecognizer,而UIGestureRecognizer繼承自NSObject)

UIPanGestureRecognizer(拖動)
UIPinchGestureRecognizer(捏合)
UIRotationGestureRecognizer(旋轉)
UITapGestureRecognizer(點按)
UILongPressGestureRecognizer(長按)
​UISwipeGestureRecognizer(輕掃)
  1. 代碼實戰的時候,通常繼承 UIGestureRecognizer 類,實現自定義手勢(手勢識別器類)一般設計成單利對象。因爲事件傳遞如果是通過Block或者是代理,那麼如果超過識別器的生命週期,手勢將不能正常響應(具體看github代碼)

    -(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;
  2. 手勢的互斥的原則
    1.手勢識別是具有互斥的原則的,比如單擊和雙擊,如果它識別出一種手勢,其後的手勢將不被識別。所以對於關聯手勢,要做特殊處理以幫助程序甄別,應該把當前手勢歸結到哪一類手勢裏面。
    2.比如,單擊和雙擊並存時,如果不做處理,它就只能發送出單擊的消息。爲了能夠識別出雙擊手勢,就需要做一個特殊處理邏輯,即先判斷手勢是否是雙擊,在雙擊失效的情況下作爲單擊手勢處理。使用
    [A requireGestureRecognizerToFail:B]函數,它可以指定當A手勢發生時,即便A已經滿足條件了,也不會立刻觸發,會等到指定的手勢B確定失敗之後才觸發。
    //添加雙擊手勢確定監測失敗纔會觸發單擊手勢的相應操作
    [tapOne requireGestureRecognizerToFail:tapTow];
  1. 如果手勢和scrollview一起使用就要防止只相應scrollView事件
    scrollView.canCancelContentTouches=NO;
    scrollView.delaysContentTouches=NO;
  1. 手勢的幾種狀態
 typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
  // 尚未識別是何種手勢操作(但可能已經觸發了觸摸事件),默認狀態
       UIGestureRecognizerStatePossible, 
  // 手勢已經開始,此時已經被識別,但是這個過程中可能發生變化,手勢操作尚未完成
       UIGestureRecognizerStateBegan,    
 // 手勢狀態發生轉變
       UIGestureRecognizerStateChanged,
 // 手勢識別操作完成(此時已經鬆開手指)   
       UIGestureRecognizerStateEnded,     
// 手勢被取消,恢復到默認狀態
       UIGestureRecognizerStateCancelled,  
 // 手勢識別失敗,恢復到默認狀態
       UIGestureRecognizerStateFailed,   
// 手勢識別完成,同UIGestureRecognizerStateEnded 
       UIGestureRecognizerStateRecognized 
       UIGestureRecognizerStateEnded 
};
  1. 手勢經常用的屬性
//設置代理,具體的協議後面會說
@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate; 
//設置手勢是否有效
@property(nonatomic, getter=isEnabled) BOOL enabled;
//獲取手勢所在的view
@property(nullable, nonatomic,readonly) UIView *view; 
//獲取觸發觸摸的點
-(CGPoint)locationInView:(nullable UIView*)view; 
//設置觸摸點數
-(NSUInteger)numberOfTouches; 
//獲取某一個觸摸點的觸摸位置
-(CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;
//這個方法中第一個參數是需要時效的手勢,第二個是生效的手勢。
-(void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
//獲取到的是手指移動後,在相對座標中的偏移量
-(CGPoint)translationInView:(nullable UIView *)view;

相對重要的BOOL屬性

@property(nonatomic) BOOL cancelsTouchesInView;
當這個屬性設置爲YES時,如果識別到了手勢,
系統將會發送touchesCancelled:withEvent:消息在其時間傳遞鏈上,
終止觸摸事件的傳遞,
設置爲NO,則不會終止事件的傳遞
@property(nonatomic) BOOL delaysTouchesBegan;
這個屬性設置手勢識別結束後,是立刻發送touchesEnded消息到事件傳遞鏈或者等待一個很短的時間後,
如果沒有接收到新的手勢識別任務,再發送。

UIGestureRecognizerDelegate

前面我們提到過關於手勢對象的協議代理,通過代理的回調,我們可以進行自定義手勢,也可以處理一些複雜的手勢關係,其中方法如下:

//手指觸摸屏幕後回調的方法,返回NO則不再進行手勢識別,方法觸發等
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
//開始進行手勢識別時調用的方法,返回NO則結束,不再觸發手勢
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
//是否支持多時候觸發,返回YES,則可以多個手勢一起觸發方法,返回NO則爲互斥
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
//下面這個兩個方法也是用來控制手勢的互斥執行的
//這個方法返回YES,第一個手勢和第二個互斥時,第一個會失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
//這個方法返回YES,第一個和第二個互斥時,第二個會失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

UIGestureRecognizer的子類介紹
一、UITapGestureRecognizer(tap點按)

  1. 點擊作爲最常用手勢,用於按下或選擇一個控件或條目(類似於普通的鼠標點擊);
  2. tap手勢屬於離散型手勢,特點是:一旦識別就無法取消,而且只會調用一次手勢操作事件(初始化手勢時指定的回調方法)

代碼

    //一次點擊
    UITapGestureRecognizer *tapOne = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapWithOne:)];
    tapOne.delegate = self;
    [self.view addGestureRecognizer:tapOne];
    //設置觸控對象的個數(幾個手指)
    [tapOne setNumberOfTouchesRequired:1];
    //點擊次數
    [tapOne setNumberOfTapsRequired:1];
    //兩次點擊
    UITapGestureRecognizer *tapTow = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapWithTow:)];
    tapTow.delegate = self;
    //一根手指操作
    [tapOne setNumberOfTouchesRequired:1];
    //點擊兩次生效
    tapTow.numberOfTapsRequired = 2;
    [self.view addGestureRecognizer:tapTow];
    //添加雙擊手勢確定監測失敗纔會觸發單擊手勢的相應操作
    [tapOne requireGestureRecognizerToFail:tapTow];
-(void)tapWithOne: (UITapGestureRecognizer *)tapOne {
    NSLog(@"被點擊了一次");
}
-(void)tapWithTow: (UITapGestureRecognizer *)tapTow {
    NSLog(@"被點擊了兩次");
}

二、 UILongPressGestureRecognizer(長按手勢 )

1.屬性:

//長點擊響應前點擊次數,默認0;
@property (nonatomic) NSUInteger numberOfTapsRequired;
//__TVOS_PROHIBITED: 用戶觸摸的手指數,默認1;
@property (nonatomic) NSUInteger numberOfTouchesRequired ;
//長按最低時間,默認0.5秒;
@property (nonatomic) CFTimeInterval minimumPressDuration;
// 手指長按期間可移動的區域,默認10像素。
@property (nonatomic) CGFloat allowableMovement;

三、UIPinchGestureRecognizer(捏合手勢 )

1.屬性:

//縮放的比例,默認爲1;
@property (nonatomic) CGFloat scale;
//縮放的速度,放大爲+,縮小爲-。
@property (nonatomic,readonly) CGFloat velocity;

四、UILongPressGestureRecognizer(長按)
長按手勢一定需要和UIGestureRecognizer類的state屬性進行配合使用,即通過不同狀態state下,實現不同的功能。
1. 基本屬性和方法

 //設置該拖動手勢處理器最多支持幾個手指拖動。
maximumNumberOfTouches:
//指定用戶至少在屏幕上按下多少秒纔會觸發該長按手勢。該默認值爲0.5
minimumPressDuration: 
//獲取該拖動手勢在指定控件上的位移。該方法返回一個CGPoint結構體數據,該結構體中x變量的值代表了水平方向的位移,y變量的值代表了垂直方向的位移。
-translationInView: 
 //獲取該拖動手勢在指定控件上的拖動速度。該方法返回一個CGPoint結構體數據,該結構體中x變量的值代表了水平方向的速度,y變量的值代表了垂直方向的速度。
-velocityInView:

五、UIRotationGestureRecognizer(旋轉)
屬性:

@property (nonatomic)          CGFloat rotation;//旋轉角度
@property (nonatomic,readonly) CGFloat velocity;//旋轉速度

**六、UIPanGestureRecognizer(拖動手勢)**
屬性:

//最小的拖動範圍
@property (nonatomic) NSUInteger minimumNumberOfTouches __TVOS_PROHIBITED;
//最大拖動範圍
@property (nonatomic) NSUInteger maximumNumberOfTouches __TVOS_PROHIBITED;
//獲取移動後相對與view的座標系的偏移量
- (CGPoint)translationInView:(nullable UIView *)view;
//獲取移動後的座標
- (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view;


**七、UISwipeGestureRecognizer**
>需要注意的是如果想要實現多方向清掃,要創建多個清掃手勢對象
屬性

//最小的掃動距離
@property(nonatomic) NSUInteger numberOfTouchesRequired;
//輕掃的方向默認UISwipeGestureRecognizerDirectionRight
@property(nonatomic) UISwipeGestureRecognizerDirection direction;
“`

手勢相關的基本知識就是這些了,如果有什麼問題歡迎大家指正,如果有興趣,大家可以下載,手勢工具類源碼查看

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章