IOS 定义手势监听器详解,利用 UIGestureRecognizer 进行捏合、旋转、平移、点击、长按手势事件响应

IOS中我们可以通过UITouch进行触摸事件监听,但是UITouch实现捏合、旋转、长按等手势事件监听非常麻烦。IOS中提供 UIGestureRecognizer 的子类帮我们简洁等实现捏合、旋转等特殊手势监听。并且一个视图可添加多个不同等手势监听器。

开启userInteractionEnabled

IOS 中UIView 默认是不可响应事件的,我们需要开启 userInteractionEnabled 方可进行事件响应。下面代码中我们创建了一个图片视图,并且开始事件响应。UIView 通过 addGestureRecognizer 进行添加手势监听器和 removeGestureRecognizer 删除手势监听器
// 创建图片视图
- (void) creareImg {
    UIImage* image = [UIImage imageNamed:@"zz.jpeg"];
    _imageView = [[UIImageView alloc] initWithImage:image];
    UIScreen* screen = [UIScreen mainScreen];
    const int width = 200;
    const int height = 100;
    const float x = screen.bounds.size.width / 2 - width / 2;
    const float y = screen.bounds.size.height / 2 - height;
    _imageView.frame = CGRectMake(x, y, width, height);
    _imageView.userInteractionEnabled = YES;
    [self.view addSubview:_imageView];
}

了解UIGestrueRecognizer

在开始使用自定义手势之前我们先了解一下 UIGestrueRecognizer 的,因为自定义都是基于 UIGestrueRecognizer 继承实现的。 UIGestrueRecognizer 是一个手势监听器,它可以设置多个手指同时触发触发事件等行为。它具有代理协议 UIGestureRecognizerDelegate 下面我来看一下它主要的属性和API、代理方法。
属性
名称 类型 说明 默认值
state UIGestureRecognizerState 当前手势状态,可分为手势开始,手势改变,手势结束等等
enabled BOOL 是否启用 YES
view UIView 手势监听的视图
requiresExclusiveTouchType BOOL 是否忽略其他手势类型,设置为YES将只响应一种手势类型 NO
numberOfTouches NSUInteger 多少根手指触发手势 1
API
  • - (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 删除事件监听函数
  • - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer 添加其他手势冲突失效器,当触发当前手势时,指定的手势将失效。
  • - (CGPoint)locationInView:(nullable UIView*)view 获取相对于指定视图的坐标位置
  • - (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view 获取指定手指相对指定视图的坐标位置
代理协议
  • - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 手势准备开启时候触发,返回NO则取消手势。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 当手势与其他手势同时发生识别时候触发,返回YES运行两个手势同时进行,返回NO则阻止同时识别。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 是否给事件接收手指。在手势开始触发事件触发前触发,返回NO可以阻止事件获取触摸的手指。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press 是否给按下事件接收手指,在按下手势事件触发前触发。返回NO可阻止事件获取触摸的手指。
我们了解清除GestureRecognizer 类,下面我们来了解其子类手势的使用。

UITapGestureRecognizer 点击手势

点击手势,可设置手指数量、点击次数触发的手势
// 创建点击手势
- (void) createTapGes {
    _imageView.userInteractionEnabled = YES; // 开启响应事件属性
    UITapGestureRecognizer* tapOneGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(big)]; // 创建手势
    tapOneGes.numberOfTapsRequired = 1; // 触发事件的点击次数
    tapOneGes.numberOfTouchesRequired = 1; // 触发事件的手指数量
    [_imageView addGestureRecognizer:tapOneGes]; // 添加手势监听器
}
// 点击触发事件
- (void) big {
    UIScreen* screen = [UIScreen mainScreen];
    [UIView beginAnimations:nil context:nil]; // 开始布局动画
    _imageView.frame = CGRectMake(0, 0, screen.bounds.size.width, screen.bounds.size.height);
    [UIView commitAnimations]; // 结束布局动画
}

UIPinchGestureRecognizer 捏合手势

捏合手势,表示双指捏合缩放的手势触发。常用于对图片查看缩放事件监听
// 捏合手势
- (void) createPinchGes {
    UIPinchGestureRecognizer* pinch = [[UIPinchGestureRecognizer alloc] init]; // 创建手势
    [pinch addTarget:self action:@selector(scale:)]; // 添加事件函数
    pinch.delegate = self; // 设置代理
    [_imageView addGestureRecognizer:pinch]; // 视图添加手势监听器
}

- (void) scale: (UIPinchGestureRecognizer*) pinch {
    UIView* IView = pinch.view; // 获取监听的视图
    CGAffineTransform transiform = CGAffineTransformScale(IView.transform, pinch.scale, pinch.scale); // 计算缩放后的矩阵
    if (transiform.a < 0.4) { // 缩放小于0.4阻止
        transiform.a = 0.4;
        transiform.d = 0.4;
    }
    IView.transform = transiform; // 重新设置矩阵
    pinch.scale = 1; // 重置缩放矩阵,否则手势会一直累加
}

// 添加允许多个手势触发代理函数
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return  YES;
}

上面代码中我们通过获取捏合手势的scale 属性获取用户捏合缩放的大小。并且使用内置api CGAffineTransformScale 重新计算了视图的2D矩阵(矩阵表示图像变形,可以了解一下图形学),注意!最后一步中必须重置手势的scale 否则会一直累加导致计算矩阵错误,如果不想重置的话那就需要修改 CGAffineTransformScale 的第一个参数为基础矩阵参数。

UIRotationGestureRecognizer 旋转手势

旋转手势,可获取用户手指旋转的角度。
// 旋转手势
- (void) createRotateGes {
    UIRotationGestureRecognizer* rotate = [[UIRotationGestureRecognizer alloc] init];
    [rotate addTarget:self action:@selector(rotate:)];
    rotate.delegate = self;
    [_imageView addGestureRecognizer:rotate];
}
// 旋转触发事件
- (void) rotate: (UIRotationGestureRecognizer*) rotate {
    UIView* IView = rotate.view;
    IView.transform =  CGAffineTransformRotate(IView.transform, rotate.rotation); // 重新计算视图矩阵
    rotate.rotation = 0;
}

UIPanGestureRecognizer 平移手势

平移动手势,比较简单就是手指移动时候触发,但是提供平移的位置和平移的速度
// 平移手势
- (void) createPanGes {
    UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    pan.delegate = self;
    [_imageView addGestureRecognizer:pan];
}
- (void) pan: (UIPanGestureRecognizer*)pan {
    CGPoint speed = [pan velocityInView:_imageView]; // 获取移动速度
    NSLog(@"x速度= %f, y速度= %f", speed.x, speed.y);
    CGPoint translation = [pan translationInView:_imageView]; // 获取移动矩阵
    CGAffineTransform transform = CGAffineTransformTranslate(_imageView.transform, translation.x, translation.y);
    _imageView.transform = transform;
}

UILongPressGestureRecognizer 长按手势

长按对应视图触发手势,可设置手指数量和手指长按时间
// 长按手势
- (void) createLongPassGes {
    UILongPressGestureRecognizer* longPass = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pass:)];
    longPass.minimumPressDuration = 1; // 设置长按触发时间,默认0.5
    [_imageView addGestureRecognizer: longPass];
}

- (void)pass: (UILongPressGestureRecognizer*) longPass {
    if (longPass.state == UIGestureRecognizerStateBegan) {
        NSLog(@"开始长按");
    } else if (longPass.state == UIGestureRecognizerStateEnded) {
        NSLog(@"结束长按");
    } else if (longPass.state == UIGestureRecognizerStateChanged) {
        NSLog(@"长按发生改变");
    }
}

UISwipeGestureRecognizer 轻滑手势

轻滑手势,类似我们的平移手势。但是轻滑不同的是在用户快速滑动时候速度,并且只提供滑动方向。
// 创建轻滑手势
- (void) createSwipe {
    UISwipeGestureRecognizer* swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swiper:)];
    swipe.direction = UISwipeGestureRecognizerDirectionDown;
    [_imageView addGestureRecognizer: swipe];
    swipe.delegate = self;
}

- (void) swiper: (UISwipeGestureRecognizer*)swiper {
    NSLog(@"发生向下滑动");
}

你可能感兴趣的:(ios,objective-c,xcode,前端)