iOS的手势识别器

一. 监听触摸事件的做法

  1. 如果想监听一个view上面的触摸事件,不使用手势实现的步骤
    (1). 自定义一个view
    (2). 实现view的touches方法,在方法内部实现具体处理代码

  2. 通过touches方法监听view触摸事件,有很明显的几个缺点
    (1). 必须得自定义view
    (2). 由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件
    (3). 不容易区分用户的具体手势行为

  3. iOS 3.2之后,苹果推出了手势识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度

二. 手势识别器简介

  1. 为了完成手势识别,必须借助于手势识别器:UIGestureRecognizer

  2. 利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势

  3. UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势

  4. UIGestureRecognizer的子类

    UITapGestureRecognizer(敲击)
    UIPinchGestureRecognizer(捏合,用于缩放)
    UIPanGestureRecognizer(拖拽)
    UISwipeGestureRecognizer(轻扫)
    UIRotationGestureRecognizer(旋转)
    UILongPressGestureRecognizer(长按)

三. UIGestureRecognizer的常见属性和方法

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) id <UIGestureRecognizerDelegate> delegate;
// 手势是否可用,默认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;

四. UIGestureRecognizer代理

注意: 使用多个手势必须使用代理

// 是否允许触发手势
- (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;

五. UIGestureRecognizer的子类常见属性和方法

1. UITapGestureRecognizer(敲击)

// 需要连续敲击几次才可触发,默认1次
@property (nonatomic) NSUInteger numberOfTapsRequired; 
// 需要几根手指一起敲击才可触发,默认1根
@property (nonatomic) NSUInteger  numberOfTouchesRequired __TVOS_PROHIBITED;

2. UIPinchGestureRecognizer(捏合,用于缩放)

提示: 模拟器快捷键:opsin + shift 向上拖“两个触摸点”

// 缩放比例
@property (nonatomic) CGFloat scale;
// 缩放速度
@property (nonatomic,readonly) CGFloat velocity;

3. UIPanGestureRecognizer(拖拽)

// 拖动的最短距离
@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;

4. UISwipeGestureRecognizer(轻扫)

// 需要几根手指一起轻扫才可触发,默认1根
@property(nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED;
// 设置轻扫方向
@property(nonatomic) UISwipeGestureRecognizerDirection direction;

5. UIRotationGestureRecognizer(旋转)

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

6. UILongPressGestureRecognizer(长按)

注意: 长安手势一般会触发两次,所有一般为了只做一次,要做一次判断

// 需要连续长按几次才可触发,默认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 () <UIGestureRecognizerDelegate>

@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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值