iOS 触摸事件与手势识别器(Gesture Recognizers)
Gesture Recognizers与触摸事件分发
通过一个问题引出今天的知识:
1.大家应该都遇见过 当需要给tableView 添加一个tap 手势识别 但是tableView 的上的事件(滑动...)还不影响,这时候应该怎么做呢?
答:应该设置tap.cancelsTouchesInView = NO; (看完下面的解释因该就知道为什么了)
一.Gesture Recognizers
Gesture Recognizers是在iOS3.2引入的,可以用来识别手势、简化定制视图事件处理的对象。Gesture Recognizers的基类为UIGestureRecognizer,这一个抽象基类,定义了实现底层手势识别行为的编程接口。在UIKit框架中提供了6个具体的手势识别类,用来识别常见的手势。这6个手势识别器类为:
- UITapGestureRecognizer:用来识别点击手势,包括单击,双击,甚至三击等。
- UIPinchGestureRecognizer:用来识别手指捏合手势。
- UIPanGestureRecognizer:用来识别拖动手势。
- UISwipeGestureRecognizer:用来识别Swipe手势。
- UIRotationGestureRecognizer:用来识别旋转手势。
- UILongPressGestureRecognizer:用来识别长按手势。
- UIScreenEdgePanGestureRecognizer:(iOS 7 新加入的手势识别器苹果官方给的唯一的一个属性是edges)
大概的意思就是UIScreenEdgePanGestureRecognizer跟pan(平移)手势差不多,需要从边缘进行拖动,在控制器转换的时候是有用的,看文档的话我们会发现 UIScreenEdgePanGestureRecognizer是 UIPanGestureRecognizer的子类,理解会更方便一点。
为了识别手势,需要将Gesture Recognizers关联到其检测触摸事件的view上,可以使用UIView的addGestureRecognizer:方法将手势识别器绑定到视图上。Gesture Recognizers在触摸事件处理流程中,处于观察者的角色,其不是view层级结构的一部分,所以也不参与responder chain。
触摸事件传递的过程:在将触摸事件发送给hit-test view之前,系统会先将触摸事件发送到hit-test view上绑定的Gesture Recognizers上或hit-test view父视图(superview)上绑定的Gesture Recognizers上。其流程大概如下图所示:

注:图中view与Gesture Recognizer的关系是,Gesture Recognizer关联在view或view的superview(可能多级)上。
二.Gesture Recognizers与事件分发路径的关系
Gesture Recognizers可能会延迟将触摸事件发送到hit-test view上,默认情况下,当Gesture Recognizers识别到手势后,会向hit-test view发送cancel消息,来取消之前发给hit-test view的事件。
控制这个流程的是UIGestureRecognizer的三个属性
- cancelsTouchesInView (默认为YES)
- delaysTouchesBegan (默认为NO)
- delaysTouchesEnded (默认为YES)
cancelsTouchesInView为YES,表示当Gesture Recognizers识别到手势后,会向hit-test view发送 touchesCancelled:withEvent:消息来取消hit-test view对此触摸序列的处理,这样只有Gesture Recognizers能响应此触摸序列,hit-test view不再响应。如果为NO,则不发送touchesCancelled:withEvent:消息给hit-test view,这样会使Gesture Recognizers和hit-test view同时响应触摸序列。
delaysTouchesBegan为NO,表示触摸序列开始时,而手势识别器还未识别出此手势时,touch事件会同时发向hit-test view,这样在手势识别器还未识别出此手势,hit-test view同时也可以收到同样的触摸事件。如果为YES,则在手势识别器在识别手势的过程中,不会有任何触摸事件发送给hit-test view,如果手势识别器最终识别到了手势,则也不会发送任何消息(包括touchesCancelled:withEvent:)给hit-test view;若干手势识别最终没有识别到手势,则所有的触摸事件在发给hit-test view处理。关于这个特性,可参考UIScrollView的delaysContentTouches属性。这样属性也谨慎使用,使用不当会导致UI无响应。
delaysTouchesEnded,在文档上的解释是,当手势识别器在识别手势时,对于UITouchPhaseEnded阶段的touch会延迟发送给hit-test view,在手势识别成功后,发送给hit-test view cancel消息,手势识别失败时,发送原来的end消息。
三.多个Gesture Recognizer之间的关系
在一个view上可以绑定多个Gesture Recognizer,在默认情况下,触摸序列中的触摸事件会以不确定的次序在各个gesture recognizer中传递,直到事件最终发送给hit-test view(如果中间没被Gesture Recognizer识别出并截获的话)。多个Gesture Recognizer之间的关系也可以根据需要定制,主要有下面几种行为
1.使其中一个gesture recognizer失败的情况下,另一个gesture recognizer才能分析事件。
以同时识别单击操作和双击操作为例,两个gesture recognizers分别用来识别单击和双击,分别为singleTapGesture和doubleTapGesture。在默认情况下,当用户进行单击操作时,singleTapGesture会识别出一个单击操作,doubleTapGesture也会识别出一个双击动作,但我们的意图是,这仅仅是一个双击操作。在这种情况下我们可以使用UIGestureRecognizer的requireGestureRecognizerToFail:方法来使singleTapGesture在doubleTapGesture识别识别的时候才分析事件,如果doubleTapGesture识别出双击事件,则singleTapGesture不会有任何动作。
[singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];
需要注意的是,在这种情况下,如果用户进行单击操作,需要一段延时(即doubleTapGesture识别失败),singleTapGesture才会识别出单击动作,进行单击处理,这段时间很多,对实际使用几乎没有影响。
2.精确控制gesture recognizer是否响应某个事件或事件序列.
在UIGestureRecognizerDelegate协议中有两个可选方法可以控制gesture recognizer是否需要识别某些事件
- gestureRecognizerShouldBegin:
此方法在gesture recognizer视图转出UIGestureRecognizerStatePossible状态时调用,如果返回NO,则转换到UIGestureRecognizerStateFailed;如果返回YES,则继续识别触摸序列.(默认情况下为YES) - gestureRecognizer:shouldReceiveTouch:
此方法在window对象在有触摸事件发生时,调用gesture recognizer的touchesBegan:withEvent:方法之前调用,如果返回NO,则gesture recognizer不会看到此触摸事件。(默认情况下为YES).
另外,在UIGestureRecognizer类中也有两个可以重写的方法来完成与Delegate方法中相同的功能
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer;
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer;
3.允许多个手势识别器共同识别
默认情况下,两个gesture recognizers不会同时识别它们的手势,但是你可以实现UIGestureRecognizerDelegate协议中的
gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法对其进行控制。这个方法在这两个gesture recognizers中的任意一个将block另一个的触摸事件时调用,如果返回YES,则两个gesture recognizers可同时识别,如果返回NO,则并不保证两个gesture recognizers必不能同时识别,因为另外一个gesture recognizer的此方法可能返回YES。也就是说两个gesture recognizers的delegate方法只要任意一个返回YES,则这两个就可以同时识别;只有两个都返回NO的时候,才是互斥的。默认情况下是返回NO。
有这样一个例子,如果要侦测在window上的所有触摸事件,可以将gesture recognizer关联到window上,默认情况下如果手势被window识别,则子视图中的gesture recognizer就失效了,而我们在window上的gesture recognizer的目的只是监控所有事件,但并不处理这些事件,具体事件的处理还需要子视图中的各个gesture recognizer去处理,这样我们可以实现window上绑定gesture recognizer的delegate方法,使gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:返回YES即可。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
四.UIScrollView的类似行为
scroll view没有滚动栏,当在scroll view上有触摸行为时其要识别出触摸行为的目的是scroll view本身还是其内容子视图。定制scrollview如何处理这种情况,看查看UIScrollView类的下列属性和方法。
– touchesShouldBegin:withEvent:inContentView:
– touchesShouldCancelInContentView:
canCancelContentTouches
delaysContentTouches
iOS 触摸事件与手势识别器(Gesture Recognizers)的更多相关文章
- IOS触摸事件和手势识别
IOS触摸事件和手势识别 目录 概述 触摸事件 手势识别 概述 为了实现一些新的需求,我们常常需要给IOS添加触摸事件和手势识别 触摸事件 触摸事件的四种方法 -(void)touchesBegan: ...
- IOS——触摸事件 视图检测和事件传递
iPhone上有非常流畅的用户触摸交互体验,能检测各种手势:点击,滑动,放大缩小,旋转.大多数情况都是用UI*GestureRecognizer这样的手势对象来关联手势事件和手势处理函数.也有时候,会 ...
- IOS 触摸事件分发机制详解
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...
- iOS中的触摸事件和手势处理
iOS中的事件可以分为三大类: 1> 触摸事件 2> 加速计事件 3> 远程控制事件 响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并 ...
- iOS开发之触摸事件及手势
1.iOS中的事件 在用户使用app过程中,会产生各种各样的事件,iOS中的事件可以分为3大类型: 2.响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并 ...
- 【原】iOS触摸事件深度解析
概述 本文主要解析从我们的手指触摸苹果设备到最终响应事件的整个处理机制.本质上讲,整个过程可以分为两个步骤: 步骤1:找目标.在iOS视图层次结构中找到触摸事件的最终接受者: 步骤2:事件响应.基于i ...
- 浅谈iOS触摸事件理解
iOS的触摸事件个人总结,分为两步: 第一步:是找到哪个视图上触摸 第二步:分析由谁去响应(响应者连) 1.寻找被触摸的视图原理如下图 hitText:withEvent:的方法处理流程: 首先会在当 ...
- iOS触摸事件
触摸常见的事件有以下几种,触摸事件一般写在view文件中,因为viewController文件有可能控制不止一个view,不适合写触摸事件 // 开始触摸 - (void)touchesBegan:( ...
- iOS触摸事件深度解析-备用
概述 本文主要解析从我们的手指触摸苹果设备到最终响应事件的整个处理机制.本质上讲,整个过程可以分为两个步骤: 步骤1:找目标.在iOS视图层次结构中找到触摸事件的最终接受者: 步骤2:事件响应.基于i ...
随机推荐
- SAP 金税接口代码 供参考
程序可以通过抓取 客户 开票信息等 下载文本 导出 需要事先创建好几个structure zc0000sdt0016, zc0000sdt0017 REPORT zc0000sdr0016 NO ST ...
- Linux下硬链接与软链接
linux下的链接文件,尤其是软链接使用非常的频繁: 链分为硬链接(hard link)与软链接(symbolic link) 两种:关键在于inode: 硬链接: 当系统需要读取一个文件时,就会去读 ...
- nginx+Uwsgi+Django总结与分析
配置与调试nginx与uwsgi 參考: 1.uWSGI其三:uWSGI搭配Nginx使用 2.学习VirtualEnv和Nginx+uwsgi用于django项目部署 3.部署备忘 4.nginx+ ...
- Linux 下 Nginx 反向代理 负载均衡配置
转载请注明出处:http://blog.csdn.net/smartbetter/article/details/52036350 上一篇分享了 Nginx + JDK + Tomcat + MySQ ...
- 新建maven指定jdk版本-eclipse新建maven项目报错The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path的解决方案
具体表现为: 使用Eclipse+Maven建立了一个Javaweb工程,JSP页面顶端出现“红色”的报错信息:The superclass "javax.servlet.http.Http ...
- C# asp.net中导出Excel表时总出现"只能在执行 Render() 的过程中调用 RegisterForEventValidation
C# asp.net中导出Excel表时总出现"只能在执行 Render() 的过程中调用 RegisterForEventValidation 后台添加以下方法:/// <summa ...
- 安卓开发笔记——WebView组件
我们专业方向本是JAVA Web,这学期突然来了个手机App开发的课设,对于安卓这块,之前自学过一段时间,有些东西太久没用已经淡忘了 准备随笔记录些复习笔记,也当做温故知新吧~ 1.什么是WebVie ...
- 简单理解AOP(面向切面编程)
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP与OOP是面向不同领域的两种设计思想. ...
- How to use base class's assignment operator in C++
看了android下的代码,好长时间没看了,有个关于C++的知识点不是很清楚,查了下: 如何使用基类中的赋值运算符? 引述自http://stackoverflow.com/questions/122 ...
- 《HTTP权威指南》学习笔记——HTTP概述
1.HTTP--因特网的多媒体信使 HTTP使用的是可靠的数据传输协议,能确保数据在传输过程中不会损坏或混乱. 2.Web客户端和服务器 Web服务器(HTTP服务器)根据客户端的请求返回服务端的数据 ...