iOS设备现如今大受欢迎的最重要原因之一就在于其开创了触控操作的潮流。发展到现在,无论是Android还是iPhone,现在APP与用户进行交互,基本上都是依赖于各种各样的触控事件。例如用户对屏幕进行了侧滑,APP就需要对这个手势进行相应的处理,给用户一个反馈。这些相应的事件就都是在UIResponder中定义的。
广告插播的措不及防:如果您要是觉得这篇文章让您有点收获,随手点个赞会让俺兴奋好久吶。
UIResponder大体有四类事件:触摸、加速计、远程控制、按压(iOS9.0以后出来的,3DTouch)。
触摸事件.png
但是在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”。
UIApplication、UIViewController、UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件。
有的童鞋可能分不清楚手势当中结束和取消的区别。举个栗子,当正在抚摸自己的爱机屏幕的时候,突然来了一个电话,这个“爱抚”的动作就被临时中断了,这个时候就叫做“取消”,而不是结束。
触摸事件分成了四部分:开始、移动、结束、取消。
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
加速计事件分成了三部分:开始、结束、取消。也有人叫做运动事件,motion events。
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
收到控制事件:
-(void)remoteControlReceivedWithEvent:(UIEvent *)event;
按压事件分成四部分:按压开始、按压改变、按压结束、按压取消。
-(void)pressesBegan:(NSSet *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
-(void)pressesChanged:(NSSet *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
-(void)pressesEnded:(NSSet *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
-(void)pressesCancelled:(NSSet *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
概念吶,我们就不说了,网上的文章应该一搜一大堆。这里是比较理论化的知识,是比较考验我们对于iOS中触摸事件的理解深度的。这里我就只是用简单的方式,写一下自己对于这部分的理解。
根据第一部分的内容,知道UIResponder有好多好多。用户点击屏幕之后,系统到底让谁来响应这个触摸事件吶?例如用户点了一个button,是应该让谁来处理呢? UIButton肯定是放在一个UIView上面,UIView也肯定是放在一个Controller里面。这几个都是响应者对象,总不能让大家一起给用户反馈吧。系统这里的原则其实是越具体越好,也就是干活的肯定是最小的那个小兵兵。要是什么事情都让UIApplication或者UIWindow干,还不让它两儿累死啊,那系统效率要低成神马样子。
最终找到这个干活的控件,我们学术上就叫做第一响应者对象。找到了负责处理的按钮之后如何给出相应处理呢?大概过程就是这样:
一次完整的触摸事件的传递响应的过程大概是这样的: UIAppliction --> UIWindow -->递归找到最适合处理事件的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者。
对于第一响应者,UIResponder提供了一系列方法,我们分别来介绍一下。
canResignFirstResponder
)且自身能成为第一响应者(canBecomeFirstResponder
)时才会成为第一响应者。换种说法就是,有人想当部门老大,那也得现在的部门头愿意放权,并且这个人还有能力才能成为老大。//判断是否能够成为第一响应者
- (BOOL)canBecomeFirstResponder
//响应者放弃第一响应者身份
- (BOOL)resignFirstResponder
- (BOOL)canResignFirstResponder
这些方法大家用的都会比较多,特别是想让文本输入框获取到焦点的时候。
//创建手势识别器对象
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
//设置手势识别器对象的具体属性,例如连续敲击2次
tap.numberOfTapsRequired = 2;
// 需要2根手指一起敲击
tap.numberOfTouchesRequired = 2;
//添加手势识别器到对应的view上
[self.iconView addGestureRecognizer:tap];
//监听手势的触发
[tap addTarget:self action:@selector(tapIconView:)];
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
// 没有触摸事件发生,所有手势识别的默认状态
UIGestureRecognizerStatePossible,
// 一个手势已经开始但尚未改变或者完成时
UIGestureRecognizerStateBegan, (类似于 touchesBegan)
// 手势状态改变
UIGestureRecognizerStateChanged, (类似于 touchesMoved)
// 手势完成
UIGestureRecognizerStateEnded, (类似于 touchesEnded)
// 手势取消,恢复至Possible状态
UIGestureRecognizerStateCancelled, (比如手指按下按钮,然后从其他地方抬起)
// 手势失败,恢复至Possible状态
UIGestureRecognizerStateFailed,
// 识别到手势识别
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
};
- (void)addLongPressGesture
{
//创建长按手势识别并添加监听事件
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
// 给图片添加长按手势
[self.imageView addGestureRecognizer:longPress];
}
//识别到长按手势后回调的方法
- (void)longPress:(UILongPressGestureRecognizer *)recognizer
{
// 判断手势的状态,长按手势一定要判断状态,否则方法会在手势开始和结束时分别调用!方法会被调用两次!
if (recognizer.state == UIGestureRecognizerStateBegan) {
//动画 改变图片的透明度
[UIView animateWithDuration:0.5 animations:^{
self.imageView.alpha = 0.5;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
self.imageView.alpha = 1.0;
}];
}];
}
}
- (void)addSwipeGesture
{
// 如果要监听多个轻扫方向,需要添加多个轻扫手势
// 轻扫手势默认支持向右的扫动方向
//创建轻扫手势识别并添加监听事件(默认是向右扫动)
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
//创建轻扫手势识别并添加监听事件
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
//direction 方向 向左轻扫
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
/**
UISwipeGestureRecognizerDirectionRight 向右轻扫(默认)不设轻扫方向 就是向右
UISwipeGestureRecognizerDirectionLeft 向左轻扫
UISwipeGestureRecognizerDirectionUp 向上轻扫
UISwipeGestureRecognizerDirectionDown 向下轻扫
*/
// 因为轻扫手势要求用户比较放松的扫动,因此最好不要将此手势添加到某一个视图上,会局限用户的操作
// 添加手势
[self.view addGestureRecognizer:swipe];
[self.view addGestureRecognizer:swipeLeft];
}
//识别到轻扫手势后回调的方法
- (void)swipe:(UISwipeGestureRecognizer *)recognizer
{
//当前获取中心位置
CGPoint from = self.imageView.center;
//目标
CGPoint to;
//向左轻扫
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
to = CGPointMake(-from.x, from.y);
} else {//向右轻扫
to = CGPointMake(3 * from.x, from.y);
}
//动画移动图片
[UIView animateWithDuration:0.5 animations:^{
self.imageView.center = to;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
self.imageView.center = from;
}];
}];
}
- (void)addPanGesture
{
//创建拖动手势 并添加手势的监听事件
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
//添加手势
[self.imageView addGestureRecognizer:pan];
}
//识别到拖动手势后回调的方法
- (void)pan:(UIPanGestureRecognizer *)recognizer
{
//获取手指按在图片上的位置 以图片左上角为原点
CGPoint translation = [recognizer translationInView:self.imageView];
// 移动图片
recognizer.view.transform = CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y);
//给平移复位 因为他是在原有基础上当前递增平移 如果不复位 或清空他会越变越大
[recognizer setTranslation:CGPointZero inView:self.imageView];
}
- (void)addPinchGesture
{
//创建缩放(捏合)手势 并添加手势的监听事件
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
//设置控制器为缩放手势的代理 可以实现同时识别两个手势
pinch.delegate = self;
[self.imageView addGestureRecognizer:pinch];
}
//识别到 缩放(捏合)手势后回调的方法
- (void)pinch:(UIPinchGestureRecognizer *)recognizer
{
//绽放图片
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
//将缩放比例复位
recognizer.scale = 1.0;
}
- (void)addRotateGesture
{
//创建缩放 旋转并添加手势的监听事件
UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotate:)];
//设置控制器为缩放手势的代理 可以实现同时识别两个手势
rotate.delegate = self;
// 添加手势
[self.imageView addGestureRecognizer:rotate];
}
//识别到旋转手势后的回调方法
- (void)rotate:(UIRotationGestureRecognizer *)recognizer
{
//图片旋转
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
//将手势识别的旋转角度复位
recognizer.rotation = 0.0; //非常重要 角度也会叠加
}
- (void)addTapGesture
{
//创建缩放点按(单击,点击)并添加手势的监听事件
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
// 添加手势
[self.imageView addGestureRecognizer:tapGesture];
}
//识别到手势后的回调方法
- (void)tap
{
NSLog(@"点我了");
}
是否支持多手势触摸的代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
谢谢您看完这么长一篇文章,辛苦啦~!点个赞吧。哈哈?