触摸事件(含手势)

一、概述

在APP的开发过程中,可能需要利用手势操作去实现一些功能或者效果。UIKit框架提供了检测常见手势的预定义手势识别器。 在手势开发上,最好尽可能使用预定义的手势识别器,因为它们的简单性减少了我们的的代码量。当然,我们也可以自定义一些特殊的手势,具体的可以查看官方文档学习:Creating a Custom Gesture Recognizer。iOS中的事件可以分为3大类型:触摸事件、加速计事件、远程控制事件,如下图:

events_to_app_2x

 

二、UIResponder

在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”,UIApplication、UIViewController、UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件。

继承了UIResponder就可以处理事件。UIResponder内部提供了以下方法来处理事件:

 

 

UIView的触摸事件处理:

UIView是UIResponder的子类,可以重写下列4个方法处理不同的触摸事件:

 

 

例如,使UIView随手指移动:

 

三:UITouch

当用户用一根手指触摸屏幕时,会创建一个与手指相关联的UITouch对象,一根手指对应一个UITouch对象

UITouch保存着跟手指相关的信息,比如触摸的位置、时间、阶段:

(1)当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置。

(2)当手指离开屏幕时,系统会销毁相应的UITouch对象。

 

UITouch的属性:

 

UITouchPhase是一个枚举类型,包含:

 

UITouch的方法:

 

四、UIEvent

每产生一个事件,就会产生一个UIEvent对象,称为事件对象,记录事件产生的时刻和类型。

常见属性:

 

一次完整的触摸过程,会经历3个状态

 

4个触摸事件处理方法中,都有NSSet *touches和UIEvent *event两个参数:

(1)一次完整的触摸过程中,只会产生一个事件对象,4个触摸方法都是同一个event参数

(2)如果两根手指同时触摸一个view,那么view只会调用一次touchesBegan:withEvent:方法,touches参数中装着2个UITouch对象

(3)如果这两根手指一前一后分开触摸同一个view,那么view会分别调用2次touchesBegan:withEvent:方法,并且每次调用时的touches参数中只包含一个UITouch对象

(4)根据touches中UITouch的个数可以判断出是单点触摸还是多点触摸

 

五、事件的产生和传递

发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中,UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理。通常,先发送事件给应用程序的主窗口(keyWindow),主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,也就是说keyWindow最先收到触摸事件。这也是整个事件处理过程的第一步,找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理:

touchesBegan…

touchesMoved…

touchedEnded…

这些touches方法的默认做法是将事件顺着响应者链条(后面会讲解)向上传递,将事件交给上一个响应者进行处理。

事件传递示例:

图片 1

触摸事件的传递是从父控件传递到子控件:

(1)点击了绿色的view:

UIApplication -> UIWindow -> 白色 -> 绿色

(2)点击了蓝色的view:

UIApplication -> UIWindow -> 白色 -> 橙色 -> 蓝色

(3)点击了黄色的view:

UIApplication -> UIWindow -> 白色 -> 橙色 -> 蓝色 -> 黄色

注意:如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件

 

UIView不接收触摸事件的三种情况

(1)不接收用户交互

userInteractionEnabled = NO

(2)隐藏

hidden = YES

(3)透明

alpha = 0.0 ~ 0.01

UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的。

 

六、响应者链条

响应者链条示意图:

iOS_responder_chain_2x

响应者链的事件传递过程

(1)如果view的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图。

(2)在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理。

(3)如果window对象也不处理,则其将事件或消息传递给UIApplication对象。

(4)如果UIApplication也不能处理该事件或消息,则将其丢弃。

 

触摸事件完整处理过程

(1)先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理事件。

(2)调用最合适控件的touches…方法。

(3)如果这个控件调用了[super touches…];就会将事件顺着相应链条往下传递,传递给上一个响应者。

(4)接着就会调用上一个响应者的touches…方法。

(5)事件还可以继续往上传递,直到UIApplication,如果UIApplication也不处理该事件或消息,则将其丢弃。

 

上一个响应者:

如果当前这个View是控制器的View,那么控制器就是上一个响应者。

如果当前这个View不是控制器的View,那么父控件就是上一个响应者。

 

对上面进行总结

发生触摸事件后,keyWindow最先拿到事件,keyWindow会在视图层次结构中找到一个最合适的视图来处理触摸事件。假设这个最合适的视图为myView,myView处理这个事件的方式为将该事件传递给自己的父View,如果父View不处理则继续往上传递,直到UIApplication。如果连UIApplication也不处理则丢弃该事件。

 

七、UIGestureRecognizer

为了完成手势识别,必须借助于手势识别器——UIGestureRecognizer,利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势,UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势:

 

手势识别器的用法:

每一个手势识别器的用法都差不多,比如UITapGestureRecognizer的使用步骤如下:

手势识别的状态:

 

例如:

添加长按手势:

 

添加轻扫手势:

 

添加拖动手势:

 

添加捏合手势:

 

添加旋转手势:

 

参考:Creating a Custom Gesture Recognizer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值