1、概念

Touch事件分发中有三个主角:Activity、ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。

View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。

View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。ViewGroup的相关的事件在View的基础上则多一个事件onInterceptTouchEvent,只对ViewGroup可响应的事件进行拦截处理。

2、理解模型

整个ViewGroup处理流程,可以看做是Touch事件在以ViewGroup为中间节点的树状结构中寻找响应。

  1. 如果用户执行一个ACTION_DOWN事件,当前View的onInterceptTouchEvent返回true,则该事件和后续的ACTION_MOVE和,ACTION_UP将不再传递到View的子控件,而是直接交由该View的onTouchEvent来处理。
  2. 如果上面onInterceptTouchEvent返回false,则该事件和后续的ACTION_UP,ACTION_MOVE将也会透过onInterceptTouchEvent,继而传递到子控件的onInterceptTouchEvent。
  3. 如果该View的onInterceptTouchEvent返回false,事件传递到目标View,然后目标View的onTouchEvent又返回了false,那么事件将继续传递到目标View的上一级的onTouchEvent。如果目标View的onTouchEvent方法返回了true,说明此事件已被处理了。

3、几条基本规则

1.如果在某个层级没有处理ACTION_DOWN事件,那么该层就再也收不到后续的Touch事件了直到下一次ACTION_DOWN事件。

说明:a.某个层级没有处理某个事件指的是它以及它的子View都没有处理该事件。

b.这条规则不适用于Activity层(它是顶层),它们可以收到每一个Touch事件。

c.如果没有处理ACTION_MOVE这类事件,不会有任何影响。

2.如果ACTION_DOWN事件发生在某个View的范围之内,则后续的ACTION_MOVE,ACTION_UP和ACTION_CANCEL等事件都将被发往该View,即使事件已经出界了。

3.第一根按下的手指触发ACTION_DOWN事件,之后按下的手指触发ACTION_POINTER_DOWN事件,中间起来的手指触发ACTION_POINTER_UP事件,最后起来的手指触发ACTION_UP事件(即使它不是触发ACTION_DOWN事件的那根手指)。

4.pointer id可以用于跟踪手指,从按下的那个时刻起pointer id生效,直至起来的那一刻失效,这之间维持不变。

5.如果一个ACTION_DOWN事件被父View拦截了,则任何子View不会再收到任何Touch事件了(这符合第1点的要求)。

6.如果一个非ACTION_DOWN事件被父View拦截了,则那些上次处理了ACTION_DOWN事件的子View会收到一个ACTION_CANCEL事件,之后不会再收到任何Touch事件了,即使父View不再拦截后续的Touch事件。

7.如果父View决定处理Touch事件或者子View没有处理Touch事件,则父View按照普通View的处理方式处理Touch事件,否则它根本不处理Touch事件(它只负责分发)。

8.如果父View在onInterceptTouchEvent中拦截了事件,则onInterceptTouchEvent中不会再收到Touch事件了,事件被直接交给它自己处理(按照普通View的处理方式)。

4、分层理解

View层:

  View的onTouch方法代码比较多,主要的逻辑分两步:

  1. 先是将事件交给TouchDelegate处理(如果有的话),如果TouchDelegate没有处理再自行处理;
  2. 自行处理主要负责View状态的变换(如按下状态),长按事件,点击事件的检测与触发等。

ViewGroup层:

ViewGroup层处理Touch事件的总体逻辑是:

  1. 先检测是否需要拦截,没有拦截的话下发给子View处理
  2. 如果子View没有处理再自行处理,自行处理的逻辑与View一样

拦截的逻辑是,将从down到up之间的所有事件看作一组事件,如果从down就拦截了,则组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了;如果是从中间拦截,则先给子View发送cancel事件,组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了。

分发的逻辑是,在ACTION_DOWN事件的时候,寻找子View进行处理,称为寻找Target;如果没有找到Target,则自行处理;如果找到Target,则交由Target处理。

从代码上看,dispatchTouchEvent负责分发逻辑,onTouchEvent负责真正的处理逻辑,一般应该重载onTouchEvent,只有特殊情况下才需要重载dispatchTouchEvent。

5、分发过程

dispatchTouchEvent是负责分发事件的,事件从activity传递出来之后,最先抵达便是最顶层view的dispatchTouchEvent,然后再进行分发,如果返回false,则交给这个view的interceptTouchEvent方法来决定是否要拦截这个事件,

  1. 如果interceptTouchEvent返回true,也就是拦截掉了,则交给它的onTouchEvent来处理,
  2. 如果interceptTouchEvent返回false,那么就传递给子view,由子view的dispatchTouchEvent再来开始这个事件的分发。

6、总结

  Touch事件机制主要有三个重要动作:事件的分发、事件的处理和拦截

  事件的分发是在Activity和ViewGroup中进行,事件的拦截就只能在ViewGroup进行,而事件的处理则可以在三个主体都进行。

http://www.cnblogs.com/frydsh/archive/2012/11/08/2760408.html

http://www.open-open.com/lib/view/open1422428386548.html

http://blog.csdn.net/chenjie19891104/article/details/7014649

http://blog.csdn.net/fastthinking/article/details/21954245

Touch事件机制的更多相关文章

  1. React-Native系列Android——Touch事件原理及状态效果

    Native原生相比于Hybrid或H5最大长处是具有流畅和复杂的交互效果,触摸事件便是当中重要一项,包括点击(Click).长按(LongClick).手势(gesture)等. 以最简单常见的点击 ...

  2. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  3. Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)

      ViewGroup View  Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...

  4. Android touch 事件传递机制

    前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...

  5. Android Touch事件传递机制解析 (推荐)

    最近新闻列表里的下拉 down up  move 等等让我十分头疼 ,无意间看到了一篇非常不错的帖子,转载如下: 开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把a ...

  6. Android Touch事件传递机制解析

    android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEven ...

  7. Android Touch事件传递机制通俗讲解

    在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给 ...

  8. (转)Android Touch事件传递机制

    -----来源:http://www.trinea.cn/android/touch-event-delivery-mechanism/ 介绍Android Touch事件的传递机制. 不少朋友私信问 ...

  9. Android Touch事件传递机制具体解释 上

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 近期总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,曾经 ...

随机推荐

  1. [label][IDE] Develop Node.js Project With WebStorm

    WebStorm 是一个支持 Node.js,CoffeeScript, TypeScript, Dart, Jade, Sass, LESS and Stylus 这些最新 web 开发技术的集成开 ...

  2. ERROR Function not available to this responsibility.Change responsibilities or contact your System Administrator.

    APPLIES TO: Navigation:  Help > Diagnostics > Custom Code > Personalize  or  Help > Diag ...

  3. s21day25 python笔记

    s21day25 python笔记 正则表达式 1.定义 定义:正则表达式是一种规则匹配字符串的规则 re模块本身只是用来操作正则表达式的,和正则本身没关系 为什么要有正则表达式? 匹配字符串 一个人 ...

  4. Spring学习(五)——集成MyBatis

    本篇我们将在上一篇http://www.cnblogs.com/wenjingu/p/3829209.html的Demo程序的基础上将 MyBatis 代码无缝地整合到 Spring 中. 数据库仍然 ...

  5. oracle 11gr2 2.04 em 更改 hostname 后无需重建资料库的方法

    1) 备份删除$ORACKE_HOME/ xxxx-sid 的EM目录:复制要创建的xxx-sid EM 名称目录: 备份删除$ORACKE_HOME/oc4j/j2ee/ xxxx-sid 的EM目 ...

  6. Windows10 下 github ssh 访问出现 Permission denied(publickey)错误的解决方法

    Windows10 下 github ssh 访问出现 Permission denied(publickey)错误的解决方法. 错误信息: git clone git@github.com:ediw ...

  7. WPF Image显示图片,文件被占用异常

    imageControl.Source = this.GetBitmapImage(imagePath);//imageControl为WPF Image控件 public BitmapImage G ...

  8. UWP开发入门(三)——{x:Bind}扩展标记

    上周打炉石打得太晚……忘记更新了,本周补上.本篇我们讲一下{x:Bind}扩展标记.{x:Bind}扩展标记也是Windows 10 Uinversal 新增的内容,按官方的说法是 {Binding} ...

  9. jquery点击页面其他位置隐藏div

    $("#btnAdd").on('click', function (e) { $("#setUp").toggle(); $(document).one('c ...

  10. 为何会有Python学习计划

    近几年感觉自己需要不断充电,从网上找寻技术潮流前端时Python映入眼帘,未来的技术,Python应该很有市场. 于是,以很低的成本从网上找到相关最新学习资料,希望自己未来的路,能坚持与书为伴,不断攀 ...