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

17 篇文章 0 订阅
4 篇文章 0 订阅

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、代理方法。

属性
名称类型说明默认值
stateUIGestureRecognizerState当前手势状态,可分为手势开始,手势改变,手势结束等等
enabledBOOL是否启用YES
viewUIView手势监听的视图
requiresExclusiveTouchTypeBOOL是否忽略其他手势类型,设置为YES将只响应一种手势类型NO
numberOfTouchesNSUInteger多少根手指触发手势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(@"发生向下滑动");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨周龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值