你真的瞭解UIGestureRecognizer嗎?,uigesturerecognizer
一:首先查看一下關於UIGestureRecognizer的定義
//當前手勢狀態typedef NS_ENUM(NSInteger, UIGestureRecognizerState) { //尚未識別是何種手勢操作(但可能已經觸發了觸摸事件),預設狀態 UIGestureRecognizerStatePossible, //手勢已經開始,此時已經被識別,但是這個過程中可能發生變化,手勢操作尚未完成 UIGestureRecognizerStateBegan, //手勢狀態發生改變 UIGestureRecognizerStateChanged, // 手勢識別操作完成(此時已經鬆開手指) UIGestureRecognizerStateEnded, //手勢被取消,恢複到預設狀態 UIGestureRecognizerStateCancelled, //手勢識別失敗,恢複到預設狀態 UIGestureRecognizerStateFailed, //手勢識別完成,同end UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded };NS_CLASS_AVAILABLE_IOS(3_2) @interface UIGestureRecognizer : NSObject//建立一個手勢對象並添加觸發事件- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action NS_DESIGNATED_INITIALIZER; //給一個手勢對象添加監聽事件- (void)addTarget:(id)target action:(SEL)action; //移除一個手勢的監聽事件- (void)removeTarget:(nullable id)target action:(nullable SEL)action; //擷取當前手勢狀態@property(nonatomic,readonly) UIGestureRecognizerState state; //委託@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate; //手勢識別是否可用@property(nonatomic, getter=isEnabled) BOOL enabled; //擷取手勢觸摸的View視圖 唯讀@property(nullable, nonatomic,readonly) UIView *view; //是否取消觸摸控制項的響應預設為YES,這種情況下當手勢辨識器識別到觸摸之後,會發送touchesCancelled給觸摸到的控制項以取消控制項view對touch的響應,這個時候只有手勢辨識器響應touch,當設定成NO時,手勢辨識器識別到觸摸之後不會發送touchesCancelled給控制項,這個時候手勢辨識器和控制項view均響應touch。注意:手勢識別和觸摸事件是同時存在的,只是因為touchesCancelled導致觸摸事件失效、@property(nonatomic) BOOL cancelsTouchesInView; //是否延遲發送觸摸事件給觸摸到的控制項預設是NO,這種情況下當發生一個觸摸時,手勢辨識器先捕捉到到觸摸,然後發給觸摸到的控制項,兩者各自做出響應。如果設定為YES,手勢辨識器在識別的過程中(注意是識別過程),不會將觸摸發給觸摸到的控制項,即控制項不會有任何觸摸事件。只有在識別失敗之後才會將觸摸事件發給觸摸到的控制項,這種情況下控制項view的響應會延遲約0.15ms。@property(nonatomic) BOOL delaysTouchesBegan; //如果觸摸識別失敗是否立即結束本次手勢識別的觸摸事件@property(nonatomic) BOOL delaysTouchesEnded; //指定一個手勢需要另一個手勢執行失敗才會執行,同時觸發多個手勢使用其中一個手勢的解決辦法有時手勢是相關聯的,如單機和雙擊,點擊和長按,點下去瞬間可能只會識別到單擊無法識別其他,該方法可以指定某一個 手勢,即便自己已經滿足條件了,也不會立刻觸發,會等到該指定的手勢確定失敗之後才觸發- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;//擷取當前觸摸在指定視圖上的點- (CGPoint)locationInView:(nullable UIView*)view; //擷取觸摸手指數- (NSUInteger)numberOfTouches; //多指觸摸的觸摸點相對於指定視圖的位置- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view; @end
UIGestureRecognizer是一個抽象類別,定義了所有手勢的基本行為,使用它的子類才能處理具體的手勢
知識點1:關於UIGestureRecognizer的子類如下(下面這些才是我們平常會直接運用到的類):
UITapGestureRecognizer(輕觸,點按)UILongPressGestureRecognizer(長按)UISwipeGestureRecognizer(撥動手勢)UIRotationGestureRecognizer(旋轉手勢)UIPanGestureRecognizer(拖拽手勢)UIPinchGestureRecognizer(捏合手勢,縮放用)
執行個體如下:
//拖拽手勢UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];[tagButton addGestureRecognizer:pan];- (void)pan:(UIPanGestureRecognizer *)pan{ }
//給視圖增加點擊動作UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapHandle:)];[self.view addGestureRecognizer:tap];-(void)tapHandle:(UITapGestureRecognizer*)tap{ }
二:關於UIGestureRecognizerDelegate代理的內容
@protocol UIGestureRecognizerDelegate <NSObject>@optional//開始進行手勢識別時調用的方法,返回NO則結束識別,不再觸發手勢,用處:可以在控制項指定的位置使用手勢識別- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;//是否支援多手勢觸發,返回YES,則可以多個手勢一起觸發方法,返回NO則為互斥是否允許多個手勢辨識器共同識別,一個控制項的手勢識別後是否阻斷手勢識別繼續向下傳播,預設返回NO;如果為YES,響應者鏈上層對象觸發手勢識別後,如果下層對象也添加了手勢並成功識別也會繼續執行,否則上層對象識別後則不再繼續傳播- (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);//手指觸控螢幕幕後回調的方法,返回NO則不再進行手勢識別,方法觸發等此方法在window對象在有觸摸事件發生時,調用gesture recognizer的touchesBegan:withEvent:方法之前調用,如果返回NO,則gesture recognizer不會看到此觸摸事件。(預設情況下為YES)- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;@end
知識點1:
//是否同時支援多種手勢- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ return YES;}//是否允許開始點擊- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{return YES;}//設定點擊的範圍- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{//擷取當前的觸摸點 CGPoint curp = [touch locationInView:self.imageView]; if (curp.x <= self.imageView.bounds.size.width*0.5) { return NO; }else{ return YES; }}
知識點2:UITapGestureRecognizer和UIButton的點擊事件衝突的解決辦法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ if ([touch.view isKindOfClass:[UIButton class]]) { return NO; } return YES;}
三:關於UIGestureRecognizer的子類知識
1:UITapGestureRecognizer(輕觸,點按)
NS_CLASS_AVAILABLE_IOS(3_2) @interface UITapGestureRecognizer : UIGestureRecognizer//設定能識別到手勢的最少的輕觸次數(預設為1)@property (nonatomic) NSUInteger numberOfTapsRequired; //設定能識別到手勢的最少的手指的個數(預設為1) @property (nonatomic) NSUInteger numberOfTouchesRequired; @end
知識點1:執行個體代碼如下
// 建立一個手勢對象UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];// 設定能識別到手勢的最少的輕觸次數tap.numberOfTapsRequired = 3;// 設定能識別到手勢的最少的手指的個數tap.numberOfTouchesRequired = 2;//把手勢對象添加到對應的控制項中[self.imgView addGestureRecognizer:tap];
2:UILongPressGestureRecognizer(長按手勢)
NS_CLASS_AVAILABLE_IOS(3_2) @interface UILongPressGestureRecognizer : UIGestureRecognizer//設定能識別到手勢的最少的輕觸次數(預設為1)@property (nonatomic) NSUInteger numberOfTapsRequired; //設定能識別到手勢的最少的手指的個數(預設為1) @property (nonatomic) NSUInteger numberOfTouchesRequired; //設定能識別到長按手勢的最短的長按時間,單位:秒,預設為0.5@property (nonatomic) CFTimeInterval minimumPressDuration; //設定長按時允許移動的最大距離,單位:像素,預設為10像素@property (nonatomic) CGFloat allowableMovement; @end
知識點1:執行個體代碼如下
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];// 設定能識別到長按手勢的最小的長按時間longPress.minimumPressDuration = 0.5;// "容錯的範圍"longPress.allowableMovement = 10;// 把長按手勢添加到對應的控制項中[self.imgView addGestureRecognizer:longPress];
3:UISwipeGestureRecognizer(撥動手勢)
typedef NS_OPTIONS(NSUInteger, UISwipeGestureRecognizerDirection) { UISwipeGestureRecognizerDirectionRight = 1 << 0, //向右滑 UISwipeGestureRecognizerDirectionLeft = 1 << 1, //向左滑 UISwipeGestureRecognizerDirectionUp = 1 << 2, //向上滑 UISwipeGestureRecognizerDirectionDown = 1 << 3 //向下滑};NS_CLASS_AVAILABLE_IOS(3_2) @interface UISwipeGestureRecognizer : UIGestureRecognizer //最少觸摸手指個數,預設為1@property(nonatomic) NSUInteger numberOfTouchesRequired; //設定撥動手勢支援的方向,預設為向右滑@property(nonatomic) UISwipeGestureRecognizerDirection direction; @end
知識點1:執行個體代碼如下
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeAction:)];swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;[self.imgView addGestureRecognizer:swipeLeft];
4:UIRotationGestureRecognizer(旋轉手勢)
NS_CLASS_AVAILABLE_IOS(3_2) @interface UIRotationGestureRecognizer : UIGestureRecognizer//旋轉的角度@property (nonatomic) CGFloat rotation; //旋轉速度,單位:度/秒、 @property (nonatomic,readonly) CGFloat velocity; @end
知識點1:執行個體代碼如下
//為圖片框添加一個旋轉手勢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;}
5:UIPanGestureRecognizer(拖拽手勢)
NS_CLASS_AVAILABLE_IOS(3_2) @interface UIPanGestureRecognizer : UIGestureRecognizer //設定觸發拖拽最少手指數,預設為1@property (nonatomic) NSUInteger minimumNumberOfTouches; //設定觸發拖拽最多手指數,預設為 UINT_MAX 無限大@property (nonatomic) NSUInteger maximumNumberOfTouches; //擷取當前拖拽位置- (CGPoint)translationInView:(nullable UIView *)view; //設定當前拖拽位置- (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view;//設定拖拽速度,單位:像素/秒- (CGPoint)velocityInView:(nullable UIView *)view; @end
知識點1:執行個體代碼
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];}
6:UIPinchGestureRecognizer(捏合手勢,縮放用)
NS_CLASS_AVAILABLE_IOS(3_2) @interface UIPinchGestureRecognizer : UIGestureRecognizer //設定縮放比例@property (nonatomic) CGFloat scale; //擷取捏合速度,單位:縮放比/秒 @property (nonatomic,readonly) CGFloat velocity; @end
知識點1:執行個體代碼
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;}