iOS学习23之事件处理

1. 事件的基本概念

 1> 概述

  事件是当用户手指触击屏幕在屏幕上移动时,系统不断发送给应用程序的对象

  系统将事件按照特定的路径传递给可以对其进行处理对象

  在iOS中,一个UITouch对象表示一个触摸,一个UIEvent对象表示一个事件。事件对象中包含与当前多点触摸序列相对应的所有触摸对象,还可以提供与特定视图窗口相关联的触摸对象

 2> 事件类型

2. 触摸的基本概念

 1> 概述

  触摸信息有时间空间两方面。

  时间方面的信息称为阶段(phrase),表示触摸是否刚刚开始、是否正在移动或处处于静止状态,以及何时结束—--也就是手指何时从屏幕抬起。

  空间方面是指当前在视图或窗口中的位置信息,以及之前的位置信息(如果有的话)。当一个手指接触屏幕时, 触摸就和某个窗口视图关联在一起,这个关联在事件的整个生命周期都会得到维护

 2> 触摸事件的阶段

 3> 触摸事件的处理方法

  在给定的触摸阶段中,如果发生新的触摸动作已有的触摸动作发生变化,应用程序就会发送这些消息: 

  当一个或多个手指触碰屏幕时,发送touchesBegan:withEvent:消息。

1 // 触摸开始
2 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
3 {
4     NSLog(@"触摸TouchView开始");
5 }

  当一个或多个手指在屏幕上移动时,发送touchesMoved:withEvent:消息。

 1 // 移动
 2 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
 3 {
 4     NSLog(@"移动TouchView");
 5     
 6     // 1.获取触摸手势
 7     UITouch *touch = [touches anyObject];
 8     
 9     // 2.获取触摸的位置
10     // locationInView: 获取一个触摸在某个视图上的位置
11     CGPoint currentPoint = [touch locationInView:self.superview];
12     
13     // 3.根据触摸的位置改变视图的位置
14     self.center = currentPoint;
15     
16 }

  当一个或多个手指离开屏幕时,发送touchesEnded:withEvent:消息。

1 // 触摸结束
2 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
3 {
4     NSLog(@"触摸TouchView结束");
5 }

  当触摸被打断时,发送touchesCancelled:withEvent:消息

1 // 触摸被打断
2 - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
3 {
4     NSLog(@"触摸TouchView被打断");
5 }

3. 响应者链

 1> 概述

  响应者链是一个响应者对象连接序列,事件动作消息(或菜单编辑消息)依次传递

  它允许响应者对象把事件处理的职责转交给其它更高层的对象。

  应用程序通过向上传递一个事件来查找合适的处理对象。因为点击检测视图也是一个响应者对象,应用程序在处理触摸事件时也可以利用响应链

   由多个响应者对象组成的链。

 2> 响应者

  iOS中所有能响应事件(触摸、晃动、远程事件)的对象都是响应者

   系统定义了一个抽象的父类UIResponder来表示响应者。其子类都是响应者。

 3> 检测视图

  硬件检测到触摸操作,会将信息交给UIApplication,开始检测。

  顺序(从最下层开始向上):UIApplication -> window -> viewController -> view -> 检测所有视图

  最终确认触碰位置,完成响应者链的查询过程

 4> 处理触摸事件

  检测到响应者后,实现touchesBegan:withEvent:等方法,即处理事件。

  如果响应者没有处理事件,事件会向下传递。如果没有响应者处理,则丢弃触摸事件

  事件处理的顺序触摸检测查询相反

  触摸的子视图 -> view -> viewController -> window -> UIApplication

 5> 阻断响应者链

  响应者链可以被打断,无法完成检测查询过程。

  视图类的属性 : userInteractionEnabled,关闭后能阻断查询过程,即值为NO时,从当前视图开始到所有的子视图不再检测

 6> 响应者链处理原则

  • 点击检测视图或者第一响应者传递事件动作消息给它的视图控制器(如果它有的话);如果没有一个视图控制器,就传递给它的父视图。 

  • 如果一个视图或者它的视图控制器不能处理这个事件或动作消息,它将传递给该视图的父视图

  • 在这个视图层次中的每个后续的父视图遵循上述的模式。

  •  最顶层的视图如果不能处理这个事件或动作消息,就传递给UIWindow对象来处理。

  •  如果UIWindow对象不能处理,就传给单件应用程序对象UIApplication,如果应用程序对象也不能处理这个事件或动作消息,将抛弃它

4. 手势

 1> 概述

  手势识别器是对触摸事件做了封装,手势识别器本身起到了识别作用

    手势识别器是iOS中比较抽象的一个类,用于识别一个手势,所谓手势:有规律的触摸

 2> 手势分类

 3> 手势识别器

  系统提供的手势识别器这个抽象父类我们是不会直接使用的,而是根据需求使用特定的手势识别器创建对象,系统所提供的手势类型如下所示:(需要将下面的方法在viewDidLoad方法中调用才能实现)

  ① UITapGestureRecognizer轻拍手势识别器,能识别轻拍操作

 1 // 创建一个轻拍手势方法
 2 - (void)tapGesture
 3 {
 4     // 1.创建手势识别器对象
 5     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureAction:)];
 6     
 7     // 2.将手势添加到相应的视图上
 8     [self.rootView.myImageView addGestureRecognizer:tap];
 9 }
10 
11 // 实现轻拍手势事件
12 - (void)tapGestureAction:(UITapGestureRecognizer *)tap
13 {
14     NSLog(@"被拍了!");
15 }

  ② UIPanGestureRecognizer平移手势识别器,能识别拖拽操作

 1 // 创建一个平移手势方法
 2 - (void)panGesture
 3 {
 4     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)];
 5     
 6     [self.rootView.myImageView addGestureRecognizer:pan];
 7 }
 8 
 9 // 实现平移手势事件
10 - (void)panGestureAction:(UIPanGestureRecognizer *)pan
11 {
12     NSLog(@"我动了...");
13     
14     // 在View上面挪动的距离,translationInView是用来获取触摸移动的距离
15     CGPoint p = [pan translationInView:pan.view];
16     
17     pan.view.transform = CGAffineTransformTranslate(pan.view.transform, p.x, p.y); // pan.view.transform 表示视图原来的位置,p.x表示移动的X轴方向的距离,p.y表示移动的Y轴方向的距离 
18     
19     // 清空移动的距离
20     [pan setTranslation:CGPointZero inView:pan.view];

  ③ UIPinchGestureRecognizer捏合手势识别器,能识别捏合操作

 1 - (void)pinchGesture
 2 {
 3     UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureAction:)];
 4     [self.rootView.myImageView addGestureRecognizer:pinch];
 5 }
 6 
 7 // 实现捏合方法
 8 - (void)pinchGestureAction:(UIPinchGestureRecognizer *)pinch
 9 {
10     pinch.view.transform = CGAffineTransformScale(pinch.view.transform, pinch.scale, pinch.scale);
11     pinch.scale = 1; // 清空移动的比例
12 }

  ④ UIRotationGestureRecognizer旋转手势识别器,能识别旋转操作

 1 // 创建一个旋转手势方法
 2 - (void)rotattionGesture
 3 {
 4     UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotattionGestureAction:)];
 5     
 6     [self.rootView addGestureRecognizer:rotation];
 7 }
 8 
 9 // 实现旋转手势事件
10 - (void)rotattionGestureAction:(UIRotationGestureRecognizer *)rotation
11 {
12     rotation.view.transform = CGAffineTransformRotate(rotation.view.transform, rotation.rotation); // rotation的旋转角度是rotation属性
13     rotation.rotation = 0;
14 }

  ⑤ UILongPressGestureRecognizer长按手势识别器,能识别长按操作

 1 // 创建一个长按手势方法
 2 - (void)longPress
 3 {
 4     UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
 5     [self.rootView.myImageView addGestureRecognizer:longPress];
 6 }
 7 
 8 // 实现长按手势事件
 9 - (void)longPressAction:(UILongPressGestureRecognizer *)longPress
10 {
11     if (longPress.state == UIGestureRecognizerStateBegan) {
12         // 设置长按的时间
13         longPress.minimumPressDuration = 2;
14         NSLog(@"长按了...");
15     }
16 }

  ⑥  UISwipeGestureRecognizer轻扫手势识别器,能识别拖拽操作

 1 // 创建一个轻扫手势方法
 2 - (void)swipe
 3 {
 4     UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeAction:)];
 5     
 6     // 设置轻扫的有效方向
 7     swipe.direction = UISwipeGestureRecognizerDirectionLeft; // 默认为Right(右)
 8     
 9     // 手指的数量
10 //    swipe.numberOfTouchesRequired = 2; // 默认为1
11     
12     [self.rootView.myImageView addGestureRecognizer:swipe];
13 }
14 
15 // 实现轻扫手势事件
16 - (void)swipeAction:(UISwipeGestureRecognizer *)swipe
17 {
18     NSLog(@"向左扫了一下!");
19 }

  ⑦ UIScreenEdgePanGestureRecognizer屏幕边缘轻扫识别器

 1 // 创建一个屏幕边缘清扫方法
 2 - (void)screenEdgePan
 3 {
 4     UIScreenEdgePanGestureRecognizer *screenEdgePan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(screenEdgePanAction:)];
 5     
 6     screenEdgePan.edges = UIRectEdgeLeft; // 所有的
 7     
 8     [self.rootView addGestureRecognizer:screenEdgePan];
 9 }
10 // 实现屏幕边缘清扫事件
11 - (void)screenEdgePanAction:(UIScreenEdgePanGestureRecognizer *)screenEdgePan
12 {
13     NSLog(@"屏幕左边缘清扫");
14 }

 4> 手势识别器使用步骤小结

  • 创建UIxxxGestureRecognizer对象,使用initWithTarget:action:方法
  • 配置要识别的手势相关信息

  • 将手势添加到某个视图上

  • 实现手势识别器里定义的方法

 5> View的transform属性

  transformview的一个重要属性,他在矩阵层面上改变view显示状态,能实现view缩放 , 旋转 , 平移等功能

  平移  CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)  t --- 表示视图原来的位置, tx --- 移动的X轴方向的距离, ty --- 移动的Y轴方向的距离
 具体使用方法见 3> ② 的代码

  缩放  CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy) t --- 表示视图原来的位置, tx --- 缩放的X轴方向的比例, ty --- 缩放的Y轴方向的比例   具体使用方法见 3> ③ 的代码

  旋转  CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)  t --- 表示视图原来的位置 , angle --- 表示旋转角度   具体使用方法见 3> ④ 的代码

 6> 通过代理实现同时识别多个手势

  ① 在需要的多个手势中设置代理

    xxx.delegate = self;

  ② 遵循协议 UIGestureRecognizerDelegate

  ③ 实现代理方法来实现同时识别多个手势

1 #pragma mark 通过代理实现同时识别多个手势
2 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
3 {
4     return YES;
5 }

 

posted @ 2016-04-09 09:42  墨隐于非  阅读(328)  评论(0编辑  收藏  举报