简介
在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件。我们称之为“响应者对象”。
UIView是UIResponder的子类,可以通过覆盖下列4个方法处理不同的触摸事件。
//当一个或多个⼿手指触碰屏幕时
//如果两根手指同时触摸某个视图,那么touchesBegan:withEvent:的第一个参数是包含两个UITouch实例的NSSet对象。
//如果这两根手指一前一后分开触摸同一个视图,那么视图会收到两个独立的touchesBegan:withEvent:消息,并且每个NSSet对象中只包含一个UITouch对象。
- (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
当用户触摸屏幕时,事件会被封装成一个event实例,包含了用户触摸的相关信息(位置信息),event实例中包含着若干个UITouch实例,touch数量表示用户的手指数量。
UIView不接收处理事件的三种情况
- 不接收用户交互:userInteractionEnabled = NO。
- 隐藏:hidden = YES。
- 透明:alpha = 0~0.01。
事件类型
触摸事件、运动事件、远程遥控事件、物理按钮事件。
typedef NS_ENUM(NSInteger, UIEventType) {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),
};
UITouch
属性和方法 | 解释 |
---|---|
window | 触摸产生时所处的窗口。由于窗口可能发生变化,当前所在的窗口不一定是最开始的窗口。 |
view | 触摸产生时所处的视图。由于视图可能发生变化,当前视图不一定是最初的视图。 |
tapCount | 轻击(Tap)操作和鼠标单击操作类似,tapCount表⽰短时间内轻击屏幕的次数。因此可以根据tapCount判断单击、双击或更多的轻击 |
timestamp | 时间戳记录了触摸事件产⽣或变化时的时间。单位是秒 |
phase | 触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。而通过phase可以查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,是一个枚举配型。 |
-(CGPoint)locationInView:(UIView *)view: | 函数返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,返回的位置是针对view坐标系的 |
-(CGPoint)previousLocationInView:(UIView *)view: | 该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值表⽰触摸view视图上的位置,返回的位置是针对view坐标系的 |
UITouchPhase
typedef NS_ENUM(NSInteger, UITouchPhase) {
UITouchPhaseBegan, //触摸开始
UITouchPhaseMoved, //接触点移动
UITouchPhaseStationary, //接触点无移动
UITouchPhaseEnded, //接触结束
UITouchPhaseCancelled, //接触取消
}
事件传递
从事件发生到其处理的对象,传递要经过特殊的一段过程。当用户点击设备屏幕时,iOS捕捉到一系列的触摸,将其打包到UIEvent对象中并放置到应用程序活动事件队列中。UIApplication对象从事件队列中取出最前面的事件并将其分发。通常发送事件给应用程序的主窗口UIWindow实例,主窗口会调用hitTest:withEvent:方法在视图继承树中找到一个最合适的子视图来处理触摸事件,该子视图即为hit-test视图。
如果hit-test视图不处理收到的事件消息,UIKit则将事件转发到响应者链中的下一个响应者,看其是否能对该消息进行处理。
响应者链
响应者对象是一个能接收并处理事件的对象。UIResponser是所有响应者对 象的基类。该基类定义了一系列编程接口,不但为事件处理进行服务而且还提供了通用的响应行为处理。UIApplication, UIView(包括 UIWindow),UIViewController都直接或间接的继承自UIResponser,所有的这些类的实例都是响应者对象。响应者链表示一系列的响应者对象。
- 当用户与视图交互时,将消息传递给视图控制器,如果不存在控制器,传递给父视图。
- 如果不处理该消息,则继续将消息向上传递。
- 最上层的视图如果也不处理,将事件交予Window对象。
- 最后交由UIApplication实 例,如果不处理,丢弃事件。
UIGestureRecognizer(手势识别器)
UIGestureRecognizer类,用于检测、识别用户使用设备时所用的手势。它是一 个抽象类,定义了所有手势的基本行为。
手势识别的状态
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
UIGestureRecognizerStatePossible,//没有触摸事件发生,所有手势识别的默认状态。
UIGestureRecognizerStateBegan,//一个手势已经开始但尚未改变或者完成时。
UIGestureRecognizerStateChanged,//手势状态改变
UIGestureRecognizerStateEnded,//手势完成
UIGestureRecognizerStateCancelled,//手势取消,恢复至Possible状态
UIGestureRecognizerStateFailed,//手势失败,恢复至Possible状态
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded//识别到手势识别
};
UIGestureRecognizer子类
UITapGestureRecognizer(轻击)
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleGesture:)];
[view addGestureRecognizer:singleTap];
- (void)singleGesture:(UITapGestureRecognizer *) tap{
NSLog(@"单击");
}
如果是双击事件,需设置tap.numberOfTapsRequired = 2;
tap.numberOfTouchesRequired = 1; //点击手指数
UIPinchGestureRecognizer(捏合)
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:@selector(pinch:)];
[view addGestureRecognizer:pinch];
static float scale = 0;
- (void)pinch:(UIPinchGestureRecognizer *)_pinch {
if(_pinch.state == UIGestureRecognizerStateEnded) {
return;
}
if(scale == 0) {
if(_pinch.scale > 0){
NSLog(@"放⼤");
}else{
NSLog(@"缩⼩");
}
}else{
if(scale - _pinch.scale < 0){
NSLog(@"放⼤");
}else{
NSLog(@"缩⼩");
}
}
scale = _pinch.scale;
}
UIPanGestureRecognizer(平移)
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[view addGestureRecognizer:panGesture];
- (void)pan:(UIPanGestureRecognizer *)_pan {
CGPoint point = [_pan locationInView:self.view];
tempView.center = point;
}
UISwipeGestureRecognizer(轻扫)
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionUp;
[view addGestureRecognizer:swipeGesture];
UIRotationGestureRecognizer(旋转)
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
[view addGestureRecognizer:rotationGesture];
- (void)rotation:(UIRotationGestureRecognizer *)_rotation {
float degress = _rotation.rotation*(180/M_PI);
tempView.transform = CGAffineTransformRotate(tempView.transform,
degress/1000);
}
UILongPressGestureRecognizer(长按)
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPressGesture.minimumPressDuration = 3;
[view addGestureRecognizer:longPressGesture];
- (void)longPress:(UILongPressGestureRecognizer *)_longPress {
NSLog(@"long press : %u", [_longPress state]);
}
UILongPressGestureRecognizer的state属性:
开始:UIGestureRecognizerStateBegan
改变:UIGestureRecognizerStateChanged
结束:UIGestureRecognizerStateEnded
取消:UIGestureRecognizerStateCancelled
失败:UIGestureRecognizerStateFailed