下面是一个触摸传递到视图和手势识别的完整的标准过程:

  • 当有一个新的触摸,该应用程序使用hit-testing命中测试(后面会讲)来确定被触摸的视图,这个视图就会永远与这个触摸对应。这个视图称为hit-test视图。如果想忽略一个视图,不处理触摸,可以在这个阶段设置userInteractionEnabled, hidden, 和 alpha属性。

  • 每次触摸状态改变,该应用程序会调用自己的sendEvent:方法,反过来又会调用window的sendEvent:方法,这个window会通过调用那几个touches...方法来传递每个事件的触摸,如下所述:

    • 当一个触摸第一次出现时,会考虑这个视图是否服从这个multipleTouchEnabled 和 exclusiveTouch逻辑,如果这个逻辑被允许,就会:

      a. 这个触摸会传递给这个hit-test视图的所有手势识别。

      b. 这个触摸会传递给hit-test视图本身。

    • 如果这个手势被一个手势识别所识别,那么对于任何与这个手势识别相关的触摸就会:

      a. touchesCancelled:forEvent:消息会发送给触摸的视图,这个触摸不再传递给它对应的视图。

      b. 如果这个触摸与任何其它的手势识别相关,这个手势识别会强制进入失败状态。

    • 如果一个手势识别失败,可能是因为它宣告失败,或因为它是被迫失败,它相关的触摸倒是不再传递给它,但(已经规定的情况除外),触摸会继续被传递到它们的视图。

  • 如果一个触摸将要传递到一个视图,如果这个视图没有响应相应的touches...方法,响应者会从响应者链向上查找可以响应的响应者,然后传递触摸给它。


hit-testing

hit-testing 是用来决定哪个视图被用户触摸了。通过使用视图的实例方法 hitTest:withEvent:,返回一个视图(hit-testing 视图)或者nil,目的是返回包含触摸点的最前面的视图。这个方法使用了一个优雅的递归算法,如下:

  1. 一个视图的hitTest:withEvent:里面会首先调用它子视图的同样方法,查找是否有hit-testing视图,因为子视图总是在父视图的前面。然后这个子视图在hitTest:withEvent:方法里面还是以相反的顺序调用它子视图的同样方法。如果两个同级的子视图重叠了,会返回最前面的那个视图。

  2. 如果一个视图hit-testing它的子视图,任何一个子视图一旦返回一个视图,那么它就会停止查询它的子视图,立刻同样返回这个视图。第一个返回的hit-test视图会沿调用链返回到顶端,这个就是最终的hit-test视图。

  3. 如果,另一方面,一个视图没有子视图,或者它的所有子视图都返回nil(表明这视图和它的子视图都没有被点击),那么这个视图就会调用它自己的pointInside:withEvent:方法。如果这个调用结果显示这个触摸是在这个视图里面的,视图会返回自身,表明它本身是hit-test 视图,否则,它返回nil。

如果一个视图有一个转换,这个仍然是正常工作的,因为pointInside:withEvent:会把视图的转换考虑进去。这就是为什么一个旋转了的button仍然正常工作。


Recognition

当一个手势识别器识别了它的手势,所有的东西都会变化。这个手势识别对应的touches 会被发送到它们的hit-test 视图的touchesCancelled:forEvent: 消息里,然后就不再到达这些视图了(除非这个手势识别的cancelsTouchesInView属性为NO)。另外,所有其它的手势识别对于这些触摸都会变成失败,同时也不再发送这些touches给这些手势识别。

依赖顺序

下面的方法建立了一个相关性顺序,使某个手势识别在其他的手势识别失败时才允许从Possible状态进入Began状态或者进入Ended状态:

  • UIGestureRecognizer 的 requireGestureRecognizerToFail:(发送到一个手势识别)

  • UIGestureRecognizer 的 shouldRequireFailureOfGestureRecognizer:(在子类中重写)

  • UIGestureRecognizer 的 shouldBeRequiredToFailByGestureRecognizer: (在子类中重写)

  • 委托的 gestureRecognizer:shouldRequireFailureOfGestureRecognizer:

  • 委托的 gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:

上面的第一个方法设置了两个手势识别的永久关系,不能撤销。其它方法就会在一个手势在视图中产生时调用,结果只适用于这个时间上的手势。

这些委托方法执行的顺序如下:对于在hit-test视图中的每对手势识别,这一对中的第一个会被发送shouldRequire消息,然后是shouldBeRequired消息,接着这一对中的第二个会被发送shouldRequire消息,然后是shouldBeRequired消息。如果任何这四种方法返回了YES,这对手势识别的关系就确定了,当前的调用序列结束,开始下一对手势识别。

成功状态到失败状态

当一个手势识别器将要声明它识别了一个手势时,如果下面的方法返回NO,会把这个手势识别强制从成功状态转到失败状态:

  • UIView 的 gestureRecognizerShouldBegin: (hit-test视图子类重写)

  • 委托的gestureRecognizerShouldBegin:

同时识别手势

一个手势识别成功了,但是其它的手势识别没有强制变成失败状态,由下面的方法决定:

  • 委托的gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:

  • UIGestureRecognizer 的 canPreventGestureRecognizer:(在子类中重写)

  • UIGestureRecognizer 的 canBePreventedByGestureRecognizer: (在子类中重写)

在子类中重写的方法名称中的“prevent” 表示“这个手势识别成功是建立在强制其它的手势失败的基础上”, 名称中的“be prevented” 表示“其它手势识别失败是建立在你这个手势识别成功”。调用顺序是:

  1. 首先调用canPreventGestureRecognizer:方法,如果返回NO,这个手势识别结束。

  2. 然后在另一个手势识别器上调用 canPreventGestureRecognizer:,如果第一次调用这个方法时返回YES,这个手势识别器会发送canBePreventedByGestureRecognizer:消息,如果这个方法也返回YES,那么这个手势识别器结束,如果返回NO,会给第二个手势识别发送 canPreventGestureRecognizer:消息,重新从1开始。

这样就解决了手势识别冲突的问题。

转载于:https://www.cnblogs.com/YungMing/p/4050134.html

触摸传递 Touch Delivery相关推荐

  1. Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作)

    Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad,移动鼠标,鼠标确定等操作) 目录 Unity 进阶 之 简单模仿鼠标交互(场景:手机屏幕当做触摸板Touch Pad ...

  2. JS事件监听手机屏幕触摸事件 Touch

    JS移动客户端--触屏滑动事件 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的t ...

  3. U3D如何调用Win10的触摸键盘Touch KeyBoard非屏幕键盘(OSK.exe)

    最近一个项目要用到Windows的触摸键盘的功能,试过OSK屏幕键盘总感觉不怎么好用,试了下Win10自带的TabTip触摸键盘发现比较符合要求这里贴上U3D呼出和隐藏触摸键盘Touch KeyBoa ...

  4. js触摸(touch)事件

    移动端触摸(touch)事件 移动端时代已经到来,作为前端开发的我们没有理由也不应该坐井观天,而是勇敢地跳出心里的那口井,去拥抱蔚蓝的天空.该来的总会来,我们要做的就是接受未知的挑战.正如你所看到的, ...

  5. Android 触摸事件(Touch)的传递机制

    Touch 事件的传递机制 一个完整的touch 事件,由一个 down 事件.n 个 move 事件,一个 up 事件组成. Touch 事 件 一 般 的 传 递 流 程 Activity--&g ...

  6. iOS UITouch触摸与UIGesture手势.01.事件、触摸(touch)事件

    一.iOS事件: 1.事件:事件就是当你在手机上点击手机屏幕.滑动手机翻面.摇动手机的时候,手机做出一些反应,对应的在应用程序里实现了某些代码的某些功能,完成这个过程就是一个事件. 2.iOS事件类型 ...

  7. HTML5滑动(swipe)事件,移动端触摸(touch)事件

    目有个交互需要实现手指滑动的交互,pc端使用mousedown,mousemove,mouseup监听实现. 但在ios设备上mousemove是不好监听的,同类的方法是touchstart,touc ...

  8. 触摸(touch)功能的原理和架构实现

    1 目前车载touch的功能,采用的都是电容屏,分为incell和oncell的概念,主要是touch panel的位置不同,主要依据touch panel 和touch IC实现touch的触摸功能 ...

  9. 触摸(Touch)事件

    Touch事件: touches:当前位于屏幕上的所有手指的一个列表 targetTouches:位于当前DOM元素上的手指的一个列表: changedTouches:涉及当前事件的手指的一个列表: ...

最新文章

  1. 用半机械器官,打开发育生物学领域的黑匣子
  2. python上机报告出现的问题和解决方法_关于发现存在问题及解决方法的报告
  3. OpenCV交互式相机校准应用
  4. hive的新分区和旧分区的概念问题
  5. vue监听对象某一个属性
  6. 58 集团大规模 Storm 任务平滑迁移至 Flink 的秘密
  7. docker 分布式管理群集_Coolpy7分布式物联网MQTT集群搭建
  8. 鸿蒙系统9月11号上市吗,9月11日鸿蒙系统2.0要搭载华为全家桶来了,你期待吗?...
  9. 获取结构体某成员偏移
  10. CMS内容管理系统可行性分析
  11. 关于PCB板热设计的学习总结
  12. matlab能打开mdl文件吗,simulink打开mdl文件的问题
  13. 基于Web的代码编辑器 Ace的使用
  14. 投稿状态(status)记录 IEEE wireless communications letters (IEEE WCL)
  15. ELK日志分析系统搭建以及springboot日志发送到ELK中
  16. 爬取公布的招聘信息(selenium实现)
  17. 【宋红康 MySQL数据库 】【高级篇】【03】MySQL的数据目录
  18. 初中数学与计算机论文,初中数学论文范文
  19. 江南大学2023年851真题回顾
  20. linux下 恢复gho镜像,手动使用ghost恢复win7系统gho镜像包教程

热门文章

  1. Dubbo学习笔记:No provider available for the service ...异常问题的解决
  2. 瞬息万变的技术圈与焦虑的技术人,进阶Android需要掌握的那几个关键技术!
  3. mysql定时任务,把7天的数据存到历史表,再删除7天前的数据
  4. Paypal学习 3 -- 接受信用卡直接付款 (DoDirectPayment)
  5. 复制链接到safari浏览器打开,如何从Safari浏览器获取网址
  6. 各种区块链浏览器的地址总汇
  7. [机器学习]1模型评估与选择
  8. 动态路由协议:华为路由配置OSPF实验
  9. 云原生kubernetes七 :Pod进阶篇:污点-容忍度-亲和性-Affinity-调度
  10. ubuntu分区大小