2.1手势识别
(一)概述
如果需要在应用程快速而轻松的处理轻按,轻扫,捏合和旋转等触摸事件,该怎么办?
答案:直接实现自定义view的touches方法.
但是这种放方式有几个明显的缺点:
1>必须得自定义view(也就是说我们开发软件界面上凡是需处理触摸事件的组件都需要自定义).
2>由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外接对象监听view的触摸事件.
3>不容易区分用户具体的手势行为(轻扫,捏合,旋转等).
4>编写代码比较繁琐.
为了解决以上这些问题,苹果公司从iOS3.2开始引入了手势识别器(UIGestureRecognizer).
UIGestureRecognizer是一个抽象类,提供了处理手势的通用框架,使用它的子类才能出来具体的手势,苹果官方为我们提供了下面常用的一些手势:
1. UITapGestureRecognizer (敲击) 2. UIPinchGestureRecognizer (捏合,用于缩放) 3. UIRotationGestureRecognizer (旋转) 4. UISwipeGestureRecognizer (轻扫) 5. UIPanGestureRecognizer (拖拽) 6. UILongPressGestureRecognizer (长按)
手势识别器的类型
1.>离散型:离散型手势识别器用来处理快捷而简单的交互,如敲击.这种类型的手势识别器一旦识别就无法取消,而且只会调用一次手势操作事件(初始化手势时指定的回调方法). 2.>连续型:连续型手势识别器需要不断的获取有关手势的信息以更新UI,如捏合和旋转.
(二)使用手势识别的步骤:
1.创建手势.
2.设置手势的属性.(通常情况下不需要设置这些属性,只需要指定所属view以及要执行的方法即可)
3.添加手势到对应的view上.
4.监听手势的触发.
// 1.创建手势
UITapGestureRecognizer *tapG = [[UITapGestureRecognizer alloc] init];
// 2.设置手势的属性
tapG.numberOfTapsRequired = 2;//需要连续敲击两次
tapG.numberOfTouchesRequired = 2;//需要两根手指一起敲击
// 3.将手势添加到view上
[chatView addGestureRecognizer:tapG];
// 4.监听手势的触发
[tapG addTarget:self action:@selector(tapGAction)];
(三)UIGestureRecognizer常用属性和方法和UIGestureRecognizerDelegate常用方法
1.>UIGestureRecognizer常用属性和方法
/*常用属性*/
// 手势的状态
@property(nonatomic,readonly) UIGestureRecognizerState state;
// 设置手势的代理
@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate; // the gesture recognizer's delegate
// 使手势可用默认为YES
@property(nonatomic, getter=isEnabled) BOOL enabled;
/*常用方法*/
// 初始一个手势并且添加手势的监听方法
- (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;
2.>UIGestureRecognizerDelegate常用方法
// 是否允许开始触发手势
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
// 是否允许支持多个手势,默认是不支持多个手势的.返回YES表示支持多个手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
// 是否允许接收手势的触摸点,获取到当前触摸点可以允许手势作用view指定的区域,如:指定view宽度的一半可以使用手势(接收触摸点),一半不可以使用手势(接收触摸点)
- (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;
}
}
(四)常用手势的使用
1>UITapGestureRecognizer(敲击)
#pragma mark - 点按手势
- (void)setUpTap
{
// 创建点按手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
// 将手势作用到对应的view上
[_imageView addGestureRecognizer:tap];
}
// 监听手势的方法
- (void)tap:(UITapGestureRecognizer *)tap
{
NSLog(@"%s",__func__);
}
2>UIPinchGestureRecognizer(捏合)
/*
注意:要在iOS模拟器中执行捏合手势,可以按住键盘Option键,将出现两个表示手指的圆圈,在移动鼠标
表示手指的圆圈将相隔更近或更远.需要调整手指中心点位置可以同时按住键盘上的shift+option键
并移动鼠标.
*/
#pragma mark - 捏合
- (void)setUpPinch
{
// 创建捏合手势并且添加监听手势的方法
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
// pinch.delegate = self; // 设置手势的代理
// 将手势作用到对应的view
[self.imageView addGestureRecognizer:pinch];
}
// 监听手势的方法
- (void)pinch:(UIPinchGestureRecognizer *)pinch
{
// 可以通过捏合手势获取对应的角度来修改view的transform属性使view可以进行捏合
self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);
// 复位
pinch.scale = 1;
}
3>UIRotationGestureRecognizer(旋转)
#pragma mark - 旋转
- (void)setUpRotation
{
// 创建一个旋转手势并且添加一个监听方法
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
// 设置手势的代理
rotation.delegate = self;
// 将手势添加到对应的view
[self.imageView addGestureRecognizer:rotation];
}
// 当旋转手势触发时调用该方法,默认传递的旋转的角度都是相对于最开始的位置
- (void)rotation:(UIRotationGestureRecognizer *)rotation
{
// 通过旋转手势获取旋转的旋转角度修改view的transform属性使view可以进行旋转
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation);
// 复位
rotation.rotation = 0;
// 获取手势旋转的角度
// NSLog(@"%f",rotation.rotation);
}
4>UISwipeGestureRecognizer(轻扫)
#pragma mark - 轻扫
/*轻扫手势支持的方法,默认为右*/
UISwipeGestureRecognizerDirectionRight = 1 << 0, // 右
UISwipeGestureRecognizerDirectionLeft = 1 << 1, // 左
UISwipeGestureRecognizerDirectionUp = 1 << 2, // 上
UISwipeGestureRecognizerDirectionDown // 下
- (void)setUpSwipe
{
// 创建一个轻扫手势并且添加监听的方法,默认轻扫的方向是往右
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
// 设置轻扫手势的方向向上
swipe.direction = UISwipeGestureRecognizerDirectionUp;
// 将手势添加到view上
[self.imageView addGestureRecognizer:swipe];
// 如果以后想要一个控件支持多个方向的轻扫,必须创建多个轻扫手势,一个轻扫手势只支持一个方向
// 默认轻扫的方向是往右
UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
// 设置轻扫手势的方向向下
swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
// 将手势添加到view上
[self.imageView addGestureRecognizer:swipeDown];
}
// 当轻扫手势触发时调用该方法
- (void)swipe
{
NSLog(@"%s",__func__);
}
5>UIPanGestureRecognizer(拖拽)
#pragma mark - 拖拽
- (void)setUpPan
{
// 创建一个拖拽手势并且添加监听方法
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
// 将拖拽手势添加到view上
[self.imageView addGestureRecognizer:pan];
}
// 当拖拽手势触发时调用该方法
- (void)pan:(UIPanGestureRecognizer *)pan
{
// 获取手势的触摸点
// CGPoint curP = [pan locationInView:self.imageView];
// 移动视图
// 获取手势的移动,也是相对于最开始的位置
CGPoint transP = [pan translationInView:self.imageView];
// 修改view的transform属性
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, transP.x, transP.y);
// 复位
[pan setTranslation:CGPointZero inView:self.imageView];
// NSLog(@"%@",NSStringFromCGPoint(curP));
}
6>UILongPressGestureRecognizer(长按)
#pragma mark - 长按
// 默认会触发两次
- (void)setUpLongPress
{
// 创建一个长按手势并且设置监听方法
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
// 将长按手势添加到view上
[self.imageView addGestureRecognizer:longPress];
}
// 当触发了长按手势时调用该方法
- (void)longPress:(UILongPressGestureRecognizer *)longPress
{
// 判断一下长按手势是否开始,如果开始可以监听
if (longPress.state == UIGestureRecognizerStateBegan) {
NSLog(@"%s",__func__);
}
}