iOS-UIGestureRecognizer详解-原理篇
UIGestureRecognizer是苹果在iOS 3.2之后,推出的手势识别功能。UIGestureRecognizer是一个抽象类,将触摸事件封装成了手势对象,大大简化了开发者的开发难度,同时也提升了用户的交互体验。UIGestureRecognizer有七个子类,它们具体实现了不同手势的功能。
UIGestureRecognizer 是一个抽象类,所以它会提供很多共有的属性和方法给子类用,这也是抽象父类的作用。
addTarget方法,允许 一个手势对象 可以 添加多个selector方法 ,并且触发的时候,所有添加的selector都会被执行,我们以点击手势示例如下:
先把所有的属性和方法列举出来说说作用的,有的属性是很常用的,就不展开说了,有的属性不常用,但是比较重要,我就单独拿出来详细说一下。
先来说说 requiresExclusiveTouchType 这个属性
是不是有很多人和我之前一样,把它理解成了设置为NO,就可以同时响应几种手势点击了呢?
这个属性的意思: 是否同时只接受一种触摸类型,而不是是否同时只接受一种手势 。默认是YES。设置成NO,它会同时响应 allowedTouchTypes 这个数组里的所有触摸类型。这个数组里面装的touchType类型如下:
如果把 requiresExclusiveTouchType 设置为NO,假设view上添加了tapGesture手势,你同时用手点击和用触控笔点击该view,这个tapGesture手势的方法都会响应。
接下来说说 cancelsTouchesInView 、 delaysTouchesBegan 、 delaysTouchesEnd 这三个属性。
cancelsTouchesInView栗子
栗子中,pan.cancelsTouchesInView = YES时,为什么会打印"touchesMoved调用了"呢?这就涉及到第二个属性 delaysTouchesBegan ,这是因为手势识别是有一个过程的,拖拽手势需要一个很小的手指移动的过程才能被识别为拖拽手势,而在一个手势触发之前,是会一并发消息给事件传递链的,所以才会有最开始的几个touchMoved方法被调用,当识别出拖拽手势以后,就会终止touch事件的传递。 当pan.cancelsTouchsInView = NO,touchesMoved和panHandler依次被打印出来,touch事件继续响应。
delaysTouchesBegan的栗子
当 delaysTouchesBegan 设置为YES时,手势识别成功之前都不会调用touches相关方法,因为手势识别成功了,所以控制台只打印了"panHandler 调用了"的信息。如果手势识别失败了,就会打印touchesMoved方法里的信息。
delaysTouchesEnd的栗子
就像上面对这个属性的分析一样 设置为NO,则会立马调用touchEnd:withEvent这个方法。设置为YES,会等待一个很短的时间,如果没有接收到新的手势识别任务,才会发送touchesEnded消息到事件传递链。
用法:[A requireGestureRecognizerToFail:B] 当A、B两个手势同时满足响应手势方法的条件时,B优先响应,A不响应。如果B不满足条件,A满足响应手势方法的条件,则A响应。其实这就是一个设置响应手势优先级的方法。
如果一个view上添加了多个手势对象的,默认这些手势是互斥的,一个手势触发了就会默认屏蔽其他手势动作。比如,单击和双击手势并存时,如果不做处理,它就只能发送出单击的消息。为了能够优先识别双击手势,我们就可以用 requireGestureRecognizerToFail: 这个方法设置优先响应双击手势。
手势可以分为: "离散手势" 和 "连续手势"
"离散手势" :比如tapGesture、swipeGesture等
"连续手势" : 比如:panGesture,rotationGesture等。
对于连续手势,手势识别器可能使状态转换更多,如下图所示:
可能---->开始----> [已更改] ---->已取消
可能---->开始----> [已更改] ---->结束
在视图上点击视图的手势------常用度五颗星
在视图上手指进行缩放的手势------常用度三颗星
在视图上手指旋转的手势------常用度三颗星
在视图上用手指进行有方向滑动的手势------常用度三颗星
在视图上用手指进行长按的手势------常用度三颗星
在视图上用手指进行平移的手势------常用度四颗星
手指在屏幕四个边缘平移的手势------常用度三颗星
从runLoop底层看事件响应和手势的关系:
如果系统提供的手势不能满足你,你也可以自定义手势。自定义手势需要继承:UIGestrureRecognizer,并且需要导入头文件#import <UIKit/UIGestureRecognizerSubclass.h>,实现以下四个方法:
更多自定义手势内容请看 这里
关于iOS-UITouch事件处理请看 UITouch事件处理-原理篇
本文借鉴了一些前辈的文章,如果有不对的地方请指正,欢迎大家一起交流学习。