用户触摸事件是依赖于响应者链来处理
-响应者链:第一响应者是视图或者其子类主要负责接收用户触摸事件;第一响应者会将事件传递给其所在的视图控制器;如果视图控制器无法处理该事件,则继续将该事件向上传递至当前App的Window;如果Window无法处理事件,则继续将该事件传递给Application。
-事件在响应者链传递过程中如果被处理则响应者链被中断
响应者对象
在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为"响应者对象".
UIApplication,UIViewController,UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件.
UIResponder内部提供了方法来处理事件;
1> 触摸事件
一次完成的触摸过程,会经历3个状态;
UIView的触摸事件处理
1、一根或多根手指开始触摸view,系统会自动调用view下面的方法:
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;//触摸开始
2、一根或者多根手指在view上移动,系统会自动调用view下面的方法(随着手指的移动,会持续调用该方法):
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event;//触摸移动
3、一根或者多根手指离开view,系统会自动调用view下面的方法:
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;//触摸结束
4、触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view下面的方法
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event;//触摸取消(可能会经历)
4个触摸事件的处理方法中,都有 NSSet *touches 和 UIEvent *event 两个参数;
1、一次完整的触摸过程,只会产生一个事件对象,4个触摸方法都是同一个event参数;
2、如果两根手指同时触摸一个view,那么view只会调用一次 touchesBegan:withEvent: 方法,touches参数中装着两个UITouch对象;
3、如果这两根手指一前一后分开触摸同一个view,那么view会分别调用两次touchesBegan:withEvent:方法, 并且每次调用时的touches参数只包含一个UITouch对象;
4、根据touches中UITouch个数可以判断出使单点触摸还是多点触摸。
提示:touches中存放的都是UITouch对象。
案例:
UIImageView类对象默认不支持接收触摸事件.
UIImageView* clickImageView = [[UIImageView alloc]initWithFrame:CGRectMake(50,50,200,380)];
clickImageView.backgroundColor= [UIColor redColor];
clickImageView.userInteractionEnabled=YES;
//针对特殊视图如果需要支持触摸事件的接收,需要打开当前视图的用户交互开关
[self.viewaddSubview:clickImageView];
//self.view.userInteractionEnabled = NO;//触摸事件是可传递的,但是任何一个视图的用户交互最终取决于当前视图的父视图(如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件。)
UIView不接收触摸事件的三种情况:
1> 不接受用户交互 :userInteractionEnable = NO;
2> 隐藏 :hidden = YES;
3> 透明:alpha = 0.0~ 0.01
提示:UIImageView的userInteractionEnable默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的。
监听触摸事件的做法
如果想监听一个view上面的触摸事件,之前的做法是:
1> 自定义一个view;
2> 实现view的touches方法,在方法内部实现具体处理代码。
通过touches方法监听view触摸事件,有很明显的几个缺点:
1> 必须得自定义view;
2> 由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件;
3> 不容易区分用户的具体手势行为。
iOS 3.2之后,苹果推出了手势识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度。
UIGestureRescognizer
为了完成手势识别,必须借助于手势识别器:UIGestureRecognizer 。
利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势。
UIGestureRecognizer是一个抽象类,定义了所有的手势基本行为,使用它的子类才能处理具体的手势
UITapGestureRecognizer(轻拍)
UIPinchGestureRecognizer(捏合,用于缩放)
UIPanGestureRecognizer(拖拽)
UISwipeGestureRecognizer(轻扫)
UIRotationGestureRecognizer(旋转)
UILongPressGestureRecognizer(长按)
每一个手势识别器的用法都差不多,使用步骤如下:
-轻拍手势识别器
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doTap:)];
//指定轻怕手势支持的触控点
//tap.numberOfTouchesRequired = 2;
//指定轻拍手势支持的轻拍次数
tap.numberOfTapsRequired=2;
[clickImageView addGestureRecognizer:tap];
-轻拍手势方法
-(void)doTap:(UITapGestureRecognizer*)tap
{
CGFloat r =arc4random()%255;
CGFloat g =arc4random()%255;
CGFloat b =arc4random()%255;
tap.view.backgroundColor= [UIColor colorWithRed:r/255 green:g/255 blue:b/255 alpha:1];
}//随机变换颜色
-长按手势识别器
UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(doLongPress:)];
//长按手势识别的最短时间(默认0.5秒)
longPress.minimumPressDuration=0.5;
//长按期间可以支持的最大移动的距离(默认10像素)
longPress.allowableMovement=10;
[clickImageView addGestureRecognizer:longPress];
-长按手势方法
-(void)doLongPress:(UILongPressGestureRecognizer * )longpress
{
if(longpress.state==UIGestureRecognizerStateBegan) {
CGFloat r =arc4random()%255;
CGFloat g =arc4random()%255;
CGFloat b =arc4random()%255;
longpress.view.backgroundColor= [UIColorcolorWithRed:r/255green:g/255blue:b/255alpha:1];
}
}
-轻扫
//一个轻扫手势识别器只能识别一个方向(默认向右)
UISwipeGestureRecognizer* swip = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(doSwip:)];
swip.direction=UISwipeGestureRecognizerDirectionLeft;
[clickImageView addGestureRecognizer:swip];
UISwipeGestureRecognizer* swip2 = [[UISwipeGestureRecognizeralloc]initWithTarget:selfaction:@selector(doSwip:)];
//swip2.direction = UISwipeGestureRecognizerDirectionLeft;
[clickImageView addGestureRecognizer:swip2];
-轻扫手势方法
-(void)doSwip:(UISwipeGestureRecognizer*)swip
{
//如果需要执行2种操作可以如下:
//if (swip.direction == UISwipeGestureRecognizerDirectionLeft) {
////执行向左事件
//}
//if (swip.direction == UISwipeGestureRecognizerDirectionRight) {
////执行向右事件
//}
CGFloatr =arc4random()%255;
CGFloatg =arc4random()%255;
CGFloatb =arc4random()%255;
swip.view.backgroundColor= [UIColor colorWithRed:r/255green:g/255blue:b/255alpha:1];
}
-拖拽手势识别器
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(doPan:)];
[clickImageView addGestureRecognizer:pan];
-拖拽手势方法
-(void)doPan:(UIPanGestureRecognizer*)pan
{
//当拖拽手势开始时保存当前拖拽的起始位置
if(pan.state==UIGestureRecognizerStateBegan) {
//保存
point= [panlocationInView:self.view];
}
//获取移动中的坐标
CGPointnewPoint = [panlocationInView:self.view];
CGFloatofffsetx = newPoint.x-point.x;
CGFloatoffsety = newPoint.y-point.y;
pan.view.center=CGPointMake(pan.view.center.x+ offfsetx, pan.view.center.y+ offsety);
point= newPoint;
//拖拽后消失
if(pan.state==UIGestureRecognizerStateEnded) {
[UIViewanimateWithDuration:0.4animations:^{
pan.view.frame=CGRectMake(pan.view.center.x, pan.view.center.y,0,0);
}];
}
}
-捏合手势识别器
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(doPinch:)];
[clickImageView addGestureRecognizer:pinch];
-捏合手势方法
-(void)doPinch:(UIPinchGestureRecognizer*)pinch
{
//按照捏合手势的比例修改图片的比例大小
pinch.view.transform=CGAffineTransformMakeScale(pinch.scale, pinch.scale);
}
-旋转手势识别器
UIRotationGestureRecognizer* rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(doRotation:)];
[clickImageView addGestureRecognizer:rotation];
-旋转手势识别器
-(void)doRotation:(UIRotationGestureRecognizer *)rotation
{
rotation.view.transform=CGAffineTransformMakeRotation(rotation.rotation);
}