UIGestureRecognizer ?手勢識別

一、概念介紹

  • UIGestureRecognizer是一個抽象類,定義了所有手勢的基本行為,使用它的子類才能處理具體的手勢

UITapGestureRecognizer(輕觸,點按)
UILongPressGestureRecognizer(長按)
UISwipeGestureRecognizer(輕掃手勢)
UIRotationGestureRecognizer(旋轉手勢)
UIPanGestureRecognizer(拖拽手勢)
UIPinchGestureRecognizer(捏合手勢,縮放用)

  • 使用步驟:
    (1)創建手勢識別對象
    (2)設置手勢識別屬性,例如手指數量,方向等
    (3)將手勢識別附加到指定的視圖之上
    (4)編寫手勢觸發監聽方法

二、UIView 的分類

方法:
1、添加一個手勢

- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;

2、移除一個手勢

- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;

3、是否接收一個手勢觸摸事件,默認為YES,返回NO為不接收

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

三、UIGestureRecognizer 抽象類

屬性:

1、獲取當前手勢狀態

@property(nonatomic,readonly) UIGestureRecognizerState state;

UIGestureRecognizerState 枚舉:
UIGestureRecognizerStatePossible 尚未識別是何種手勢操作(但可能已經觸發了觸摸事件),默認狀態
UIGestureRecognizerStateBegan 手勢已經開始,此時已經被識別,但是這個過程中可能發生變化,手勢操作尚未完成
UIGestureRecognizerStateChanged 手勢狀態發生改變
UIGestureRecognizerStateEnded 手勢識別操作完成(此時已經松開手指)
UIGestureRecognizerStateCancelled 手勢被取消,恢復到默認狀態
UIGestureRecognizerStateFailed 手勢識別失敗,恢復到默認狀態
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded 手勢識別完成,同end

2、手勢識別是否可用

@property(nonatomic, getter=isEnabled) BOOL enabled;

3、獲取手勢觸摸的View視圖

@property(nullable, nonatomic,readonly) UIView *view;  

4、是否取消觸摸控件的響應
默認為YES,這種情況下當手勢識別器識別到觸摸之后,會發送touchesCancelled給觸摸到的控件以取消控件view對touch的響應,這個時候只有手勢識別器響應touch,當設置成NO時,手勢識別器識別到觸摸之后不會發送touchesCancelled給控件,這個時候手勢識別器和控件view均響應touch。
注意:手勢識別和觸摸事件是同時存在的,只是因為touchesCancelled導致觸摸事件失效、

@property(nonatomic) BOOL cancelsTouchesInView;

5、是否延遲發送觸摸事件給觸摸到的控件
默認是NO,這種情況下當發生一個觸摸時,手勢識別器先捕捉到到觸摸,然后發給觸摸到的控件,兩者各自做出響應。如果設置為YES,手勢識別器在識別的過程中(注意是識別過程),不會將觸摸發給觸摸到的控件,即控件不會有任何觸摸事件。只有在識別失敗之后才會將觸摸事件發給觸摸到的控件,這種情況下控件view的響應會延遲約0.15ms。

@property(nonatomic) BOOL delaysTouchesBegan;

6、如果觸摸識別失敗是否立即結束本次手勢識別的觸摸事件(讓觸摸控件去識別觸摸事件)
默認為YES,這種情況下發生一個觸摸時,在手勢識別成功后,發送給touchesCancelled消息給觸摸控件view,手勢識別失敗時,會延遲大概0.15ms,期間沒有接收到別的觸摸才會發送touchesEnded觸摸結束方法,如果設置為NO,則不會延遲,即會立即發送touchesEnded以結束當前觸摸。

@property(nonatomic) BOOL delaysTouchesEnded;

7、 UIGestureRecognizerDelegate 代理

@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate;

方法:

1、創建一個手勢對象并添加觸發事件

- (instancetype)initWithTarget:(nullableid)target action:(nullableSEL)action;

2、給一個手勢對象添加監聽事件

- (void)addTarget:(id)target action:(SEL)action;

3、移除一個手勢的監聽事件

- (void)removeTarget:(nullable id)target action:(nullable SEL)action;

4、指定一個手勢需要另一個手勢執行失敗才會執行,同時觸發多個手勢使用其中一個手勢的解決辦法
有時手勢是相關聯的,如單機和雙擊,點擊和長按,點下去瞬間可能只會識別到單擊無法識別其他,該方法可以指定某一個 手勢,即便自己已經滿足條件了,也不會立刻觸發,會等到該指定的手勢確定失敗之后才觸發

- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;

例子:

// 關鍵在這一行,如果雙擊確定偵測失敗才會觸發單擊
[singleRecognizer requireGestureRecognizerToFail:doubleRecognizer];

5、獲取當前觸摸在指定視圖上的點

- (CGPoint)locationInView:(nullable UIView*)view;  

6、獲取觸摸手指數

- (NSUInteger)numberOfTouches; 

7、多指觸摸的觸摸點相對于指定視圖的位置

- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;

四、UIGestureRecognizerDelegate 代理方法

處理一些同時進行的手勢操作:
1、 開始進行手勢識別時調用的方法,返回NO則結束識別,不再觸發手勢,用處:可以在控件指定的位置使用手勢識別

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

2、手指觸摸屏幕后回調的方法,返回NO則不再進行手勢識別,方法觸發等
此方法在window對象在有觸摸事件發生時,調用gesture recognizer的touchesBegan:withEvent:方法之前調用,如果返回NO,則gesture recognizer不會看到此觸摸事件。(默認情況下為YES)

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

例子:UITapGestureRecognizer和UIButton的點擊事件沖突的解決辦法

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{    
if ([touch.view isKindOfClass:[UIButton class]])    { 
       return NO;    }   
       return YES;
}

3、手指按壓屏幕后回調的方法,返回NO則不再進行手勢識別,方法觸發等

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press;

4、 是否支持多手勢觸發,返回YES,則可以多個手勢一起觸發方法,返回NO則為互斥
是否允許多個手勢識別器共同識別,一個控件的手勢識別后是否阻斷手勢識別繼續向下傳播,默認返回NO;如果為YES,響應者鏈上層對象觸發手勢識別后,如果下層對象也添加了手勢并成功識別也會繼續執行,否則上層對象識別后則不再繼續傳播

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

5、下面這個兩個方法也是用來控制手勢的互斥執行的
(1) 這個方法返回YES,第一個手勢和第二個互斥時,第一個會失效

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

(2) 這個方法返回YES,第一個和第二個互斥時,第二個會失效

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

五、UITapGestureRecognizer(輕觸,點按)

1、 設置能識別到手勢的最少的輕觸次數(默認為1)

@property (nonatomic) NSUInteger  numberOfTapsRequired;

2、 設置能識別到手勢的最少的手指的個數(默認為1)

@property (nonatomic) NSUInteger  numberOfTouchesRequired;

例子:

// 創建一個手勢對象
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
// 設置能識別到手勢的最少的輕觸次數
tap.numberOfTapsRequired = 3;
// 設置能識別到手勢的最少的手指的個數
tap.numberOfTouchesRequired = 2;
//把手勢對象添加到對應的控件中
[self.imgView addGestureRecognizer:tap];

六、UILongPressGestureRecognizer(長按手勢)

1、最少觸摸次數,默認為0

@property (nonatomic) NSUInteger numberOfTapsRequired;

2、最少觸摸手指個數,默認為1

@property (nonatomic) NSUInteger numberOfTouchesRequired;、

3、 設置能識別到長按手勢的最短的長按時間,單位:秒,默認為0.5

@property (nonatomic) CFTimeInterval minimumPressDuration;

4、設置長按時允許移動的最大距離,單位:像素,默認為10像素

@property (nonatomic) CGFloat allowableMovement; 

例子:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
// 設置能識別到長按手勢的最小的長按時間
longPress.minimumPressDuration = 0.5;
// "容錯的范圍"
longPress.allowableMovement  = 10;
// 把長按手勢添加到對應的控件中
[self.imgView addGestureRecognizer:longPress];

七、UISwipeGestureRecognizer(輕掃手勢)

1、最少觸摸手指個數,默認為1

@property(nonatomic) NSUInteger numberOfTouchesRequired;

2、設置輕掃手勢支持的方向,默認為向右滑

@property(nonatomic) UISwipeGestureRecognizerDirection direction; 

枚舉值:
UISwipeGestureRecognizerDirectionRight 向右滑
UISwipeGestureRecognizerDirectionLeft 向左滑
UISwipeGestureRecognizerDirectionUp 向上滑
UISwipeGestureRecognizerDirectionDown 向下滑

例子:

UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeAction:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imgView addGestureRecognizer:swipeLeft];

八、UIRotationGestureRecognizer(旋轉手勢)

1、旋轉的角度

@property (nonatomic) CGFloat rotation;

2、旋轉速度,單位:度/秒、

@property (nonatomic,readonly) CGFloat velocity;

例子:

//為圖片框添加一個旋轉手勢
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateAction:)];rotation.delegate = self;
[self.imgView addGestureRecognizer:rotation];
// 旋轉手勢的監聽方法
- (void)rotateAction:(UIRotationGestureRecognizer *)recognizer {
// 在原來的基礎上, 累加多少度
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
// 每次旋轉完畢后將rotation的值, 恢復到0的位置.recognizer.rotation = 0;
}

九、UIPanGestureRecognizer(拖拽手勢)

1、設置觸發拖拽最少手指數,默認為1

@property (nonatomic) NSUInteger minimumNumberOfTouches;

2、設置觸發拖拽最多手指數,默認為 UINT_MAX 無限大

@property (nonatomic) NSUInteger maximumNumberOfTouches;

3、獲取當前拖拽位置

- (CGPoint)translationInView:(nullable UIView *)view;

4、設置當前拖拽位置

- (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view;

5、設置拖拽速度,單位:像素/秒

- (CGPoint)velocityInView:(nullable UIView *)view;

例子:

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[self.imgView addGestureRecognizer:pan];
// 拖拽手勢的監聽方法
- (void)panAction:(UIPanGestureRecognizer *)recognizer {
// 1. 獲取手指拖拽的時候, 平移的值
CGPoint translation = [recognizer translationInView:recognizer.view];
// 2. 讓當前控件做響應的平移
recognizer.view.transform = CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y);
// 3. 每次平移手勢識別完畢后, 讓平移的值不要累加
[recognizer setTranslation:CGPointZero inView:recognizer.view];
}

十、UIPinchGestureRecognizer(捏合手勢,縮放用)

1、設置縮放比例

@property (nonatomic) CGFloat scale;

2、獲取捏合速度,單位:縮放比/秒

@property (nonatomic,readonly) CGFloat velocity;

例子:

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchAction:)];pinch.delegate = self;
[self.imgView addGestureRecognizer:pinch];
// 捏合手勢監聽方法
- (void)pinchAction:(UIPinchGestureRecognizer *)recognizer {
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1.0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容