如果想監聽一個view上面的觸摸事件,不使用手勢實現的步驟
(1). 自定義一個view
(2). 實現view的touches方法,在方法內部實現具體處理代碼
通過touches方法監聽view觸摸事件,有很明顯的幾個缺點
(1). 必須得自定義view
(2). 由於是在view內部的touches方法中監聽觸摸事件,因此默認情況下,無法讓其他外界對象監聽view的觸摸事件
(3). 不容易區分用戶的具體手勢行為
iOS 3.2之後,蘋果推出了手勢識別功能(Gesture Recognizer),在觸摸事件處理方面,大大簡化了開發者的開發難度
為了完成手勢識別,必須借助於手勢識別器:UIGestureRecognizer
利用UIGestureRecognizer,能輕松識別用戶在某個view上面做的一些常見手勢
UIGestureRecognizer是一個抽象類,定義了所有手勢的基本行為,使用它的子類才能處理具體的手勢
UIGestureRecognizer的子類
UITapGestureRecognizer(敲擊)
UIPinchGestureRecognizer(捏合,用於縮放)
UIPanGestureRecognizer(拖拽)
UISwipeGestureRecognizer(輕掃)
UIRotationGestureRecognizer(旋轉)
UILongPressGestureRecognizer(長按)
UIGestureRecognizer繼承於NSObject
// 初始化手勢要觸發的對象與事件 - (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action // 添加手勢要觸發的對象與事件 - (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) iddelegate; // 手勢是否可用,默認YES @property(nonatomic, getter=isEnabled) BOOL enabled; // 只讀,手勢所屬的視圖 @property(nullable, nonatomic,readonly) UIView *view; // 默認YES.意思就是說一旦手勢被識別,那麼就調用[touchView touchesCancelled:withEvent] @property(nonatomic) BOOL cancelsTouchesInView; // 默認NO.意思就是再手勢識別成功之前,touchObj還是要分發到touchView. // 設置為YES的時候就表示從手勢識別成功之前touchObj不給touchView分發 @property(nonatomic) BOOL delaysTouchesBegan; // 默認YES:在手勢識別成功之前,touchesEnded不會被調用。 // 設置為NO:在手勢識別成功之前,touchesEnded會被調用 @property(nonatomic) BOOL delaysTouchesEnded; // 當指定的識別器(調用者)識別失敗,才去識別另一個識別器otherGestureRecognizer - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer; // 獲取手勢識別器的觸摸點 - (CGPoint)locationInView:(nullable UIView*)view; // 獲取手勢識別器的觸摸點個數 - (NSUInteger)numberOfTouches; // 指定觸摸點的位置 - (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;
注意: 使用多個手勢必須使用代理
// 是否允許觸發手勢 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; // 是否允許多個同時支持多個手勢,默認不允許,手勢必須要設置代理 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; // 這個方法在這兩個gesture recognizers中的任意一個將堵塞另一個的觸摸事件時調用, // 如果返回YES,則兩個gesture recognizers可同時識別, // 如果返回NO,則並不保證兩個gesture recognizers必不能同時識別, // 因為另外一個gesture recognizer的此方法可能返回YES。 // 也就是說兩個gesture recognizers的delegate方法只要任意一個返回YES,則這兩個就可以同時識別; // 只有兩個都返回NO的時候,才是互斥的。默認情況下是返回NO - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0); // 是否允許手勢識別器識別失敗的時候使用另一個識別器otherGestureRecognizer - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0); // 是否允許接收觸摸點 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch; // 是否允許接收長按點 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press;
// 需要連續敲擊幾次才可觸發,默認1次 @property (nonatomic) NSUInteger numberOfTapsRequired; // 需要幾根手指一起敲擊才可觸發,默認1根 @property (nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED;
提示: 模擬器快捷鍵:opsin + shift 向上拖“兩個觸摸點”
// 縮放比例 @property (nonatomic) CGFloat scale; // 縮放速度 @property (nonatomic,readonly) CGFloat velocity;
// 拖動的最短距離 @property (nonatomic) NSUInteger minimumNumberOfTouches __TVOS_PROHIBITED; // 拖動的最長距離 @property (nonatomic) NSUInteger maximumNumberOfTouches __TVOS_PROHIBITED; // 在指定的view上得坐標 - (CGPoint)translationInView:(nullable UIView *)view; // 設置在view中移動以後的坐標為translation - (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view; // 拖動view,返回的值就用於計算view相對於父控件拖動的速度 - (CGPoint)velocityInView:(nullable UIView *)view;
// 需要幾根手指一起輕掃才可觸發,默認1根 @property(nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED; // 設置輕掃方向 @property(nonatomic) UISwipeGestureRecognizerDirection direction;
// 旋轉角度 @property (nonatomic) CGFloat rotation; // 旋轉速度 @property (nonatomic,readonly) CGFloat velocity;
注意: 長安手勢一般會觸發兩次,所有一般為了只做一次,要做一次判斷
// 需要連續長按幾次才可觸發,默認0次 @property (nonatomic) NSUInteger numberOfTapsRequired; // 需要幾根手指一起長按才可觸發,默認1根 @property (nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED; // 最小長按時間 @property (nonatomic) CFTimeInterval minimumPressDuration; // 允許移動距離 @property (nonatomic) CGFloat allowableMovement;
#import "ViewController.h" @interface ViewController ()@property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self setUpTap]; [self setUpLongPress]; [self setUpSwipe]; [self setUpRotation]; [self setUpPinch]; [self setUpPan]; } #pragma mark - 點按手勢 - (void)setUpTap { UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionUpTap)]; // 多個手勢必須要代理 gestureRecognizer.delegate = self; [_imageView addGestureRecognizer:gestureRecognizer]; } - (void)actionUpTap { NSLog(@"點按手勢"); } #pragma mark - 長按手勢 - (void)setUpLongPress { UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(actionLongPress)]; gestureRecognizer.delegate = self; [_imageView addGestureRecognizer:gestureRecognizer]; } - (void)actionLongPress { NSLog(@"長按手勢"); } #pragma mark - 輕掃手勢 - (void)setUpSwipe{ // 默認向右輕掃,如果要同時有多個輕掃方向,必須要創建輕掃對象 UISwipeGestureRecognizer *gestureRecognizerRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)]; [_imageView addGestureRecognizer:gestureRecognizerRight]; UISwipeGestureRecognizer *gestureRecognizerLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)]; // 向左輕掃 gestureRecognizerLeft.direction = UISwipeGestureRecognizerDirectionLeft; [_imageView addGestureRecognizer:gestureRecognizerLeft]; UISwipeGestureRecognizer *gestureRecognizerUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)]; // 向上輕掃 gestureRecognizerUp.direction = UISwipeGestureRecognizerDirectionUp; [_imageView addGestureRecognizer:gestureRecognizerUp]; UISwipeGestureRecognizer *gestureRecognizerDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)]; // 向下輕掃 gestureRecognizerDown.direction = UISwipeGestureRecognizerDirectionDown; [_imageView addGestureRecognizer:gestureRecognizerDown]; } - (void)actionSwipe { NSLog(@"輕掃手勢"); } #pragma mark - 旋轉手勢 - (void)setUpRotation { UIRotationGestureRecognizer *gestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(actionRotation:)]; gestureRecognizer.delegate = self; [_imageView addGestureRecognizer:gestureRecognizer]; } - (void)actionRotation:(UIRotationGestureRecognizer *)rotation { _imageView.transform = CGAffineTransformRotate(_imageView.transform, rotation.rotation); // 復位 rotation.rotation = 0; } #pragma mark - 捏合手勢 - (void) setUpPinch { UIPinchGestureRecognizer *gestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(actionPinch:)]; gestureRecognizer.delegate = self; [_imageView addGestureRecognizer:gestureRecognizer]; } - (void)actionPinch:(UIPinchGestureRecognizer *)pinch { _imageView.transform = CGAffineTransformScale(_imageView.transform, pinch.scale, pinch.scale); // 復位 pinch.scale = 1; } #pragma mark - 拖拽手勢 - (void)setUpPan { UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(actionPan:)]; gestureRecognizer.delegate = self; [_imageView addGestureRecognizer:gestureRecognizer]; } - (void)actionPan:(UIPanGestureRecognizer *)pan { //NSLog(@"%ld",[pan numberOfTouches]); // 獲取手勢的觸摸點 // CGPoint curP = [pan locationInView:self.imageView]; CGPoint panTrans = [pan translationInView:_imageView]; _imageView.transform = CGAffineTransformTranslate(_imageView.transform, panTrans.x, panTrans.y); // 復位 [pan setTranslation:CGPointZero inView:_imageView]; } #pragma mark - 手勢代理 // 是否允許多個同時支持多個手勢,默認不允許,手勢必須要設置代理 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } // 是否允許觸發手勢事件 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { return YES; } // 是否允許接收觸摸點 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { return YES; } @end