Action_Down

当按下一个控件,调用流程是Activity.dispatchTouchEvent -> ViewGroup.dispatchTouchEvent ,

1、ViewGroup.dispatchTouchEvent返回true会消费掉当前的event,不会调用当前ViewGroup的onTouchEvent。

2、ViewGroup.dispatchTouchEvent返回false会调用父控件的onTouchEvent方法。并且逐级往上层回溯onTouchEvent。

3、如果ViewGroup要拦截event, ViewGroup.dispatchTouchEvent中调用的onInterceptTouchEvent返回true就会拦截当前事件,拦截到event,会在当前ViewGroup中调用onTouchEvent来处理event, onTouchEvent返回false则继续往父控件回溯; 返回true, 表示已消费当前事件,不再回溯。

如果onInterceptTouchEvent返回false, 就会调用子控件的dispatchTouchEvent,一次类推,继续下去。

4、View的disPatchTouchEvent如果返回true就会消费掉event,不会再传递给onTouchEvent。如果View要拦截Event,使得event消费在View的onTouchEvent中,由于View中没有onInterceptTouchEvent,怎么样传递给当前View的onTouchEvent呢? 答案是通过调用super.dispatchTouchEvent(在其内部调用到onTouchEvent)。

5、一旦event进入到onTouchEvent中去处理,当前处理的onTouchEvent返回false会从下往上调用父控件的onTouchEvent, 知道控件的onTouchEvent返回true, 表示将该event消费掉。

总结:dispatchTouchEvent返回true和ViewGroup的onInterceptTouchEvent返回true以及onTouchEvent返回true会消费掉事件。

而真正处理事件的函数是可能是dispatchTouchEvent或者onTouchEvent,因为onInterceptTouchEvent返回true会在onTouchEvent中消费。

dispatchTouchEvent方法能把事件分发到自己的onTouchEvent处理呢,return true和false 都不行,那么只能通过Interceptor把事件拦截下来给自己的onTouchEvent,所以ViewGroup dispatchTouchEvent方法的super默认实现就是去调用onInterceptTouchEvent

Action_Move和Action_Up

Action_Down会按照从上往下,寻找消费事件。

如果消费事件是卡在dispatchTouchEvent那么Action_Move和Action_Up调用流程与Action_Down一致,都是同样流程被dispatchTouchEvent消费掉。

如果消费事件是在onTouchEvent函数,Action_Move和Action_Up调用流程将会是在对应的dispatchTouchEvent->onTouchEvent消费,不会向下传递。而Action_Down会走完一个完整的流程。

图片出自http://www.jianshu.com/p/e99b5e8bd67b

源码:

1、Activity中的dispatchTouchEvent:

根据官方文档注释,当有任意一个按键、触屏或者轨迹球事件发生时,栈顶Activity的onUserInteraction会被触发。如果我们需要知道用户是不是正在和设备交互,可以在子类中重写这个方法,去获取通知(比如取消屏保这个场景)。(参考 http://allenfeng.com/2017/02/22/android-touch-event-transfer-mechanism/)

2765行,getWindow().superDispatchTouchEvent(ev);getWindow是mWindow, mWindow实际上是PhoneWindow,所以

调用DecorView中的superDispatchTouchEvent

上图表明在DecorView中调用的是父类的dispatchTouchEvent(FrameLayout中没有重写dispatchTouchEvent,所以调用ViewGroup中的dispatchTouchEvent)

现在回到Activity的dispatchTouchEvent看,如果getWindow().superDispatchTouchEvent(ev)返回false, 会调用Activity的onTouchEvent。

2、继续分析在ViewGroup中开始调用dispatchTouchEvent

具体分析见http://allenfeng.com/2017/02/22/android-touch-event-transfer-mechanism/

重点说一处,在Action_Down的后续事件Action_Move或者Action_Up等事件,会传递至mFirstTouchTarget中保存的目标子View中,如果在上一节遍历过程中已经把本次事件传递给子View,alreadyDispatchedToNewTouchTarget的值会被设置为true,代码会判断alreadyDispatchedToNewTouchTarget的值,避免做重复分发。简单的说一个View没有消费Action_Down事件,后续的事件也不会传递近来。

3、View的dispatchTouchEvent

如果ViewGroup没有消费事件最终会调用到View的dispatchTouchEvent。

View首先会调用onTouch,如果它返回true,那么onTouchEvent将得不到执行,事件传递终止,否则会即系传递,直到onTouchEvent返回true消费事件。

onInterceptTouchEvent默认是不拦截的,即返回false;如果你需要拦截,只要return true就行了,这要该事件就不会往子View传递了,并且如果你在DOWN retrun true ,则DOWN,MOVE,UP子View都不会捕获事件;如果你在MOVE return true , 则子View在MOVE和UP都不会捕获事件。

原因很简单,当onInterceptTouchEvent(ev) return true的时候,会把mMotionTarget 置为null ;

getParent().requestDisallowInterceptTouchEvent(true);  这样即使ViewGroup在MOVE的时候return true,子View依然可以捕获到MOVE以及UP事件。

Android事件分发流程总结的更多相关文章

  1. Android事件分发机制三:事件分发工作流程

    前言 很高兴遇见你~ 本文是事件分发系列的第三篇. 在前两篇文章中,Android事件分发机制一:事件是如何到达activity的? 分析了事件分发的真正起点:viewRootImpl,Activit ...

  2. Android事件分发机制(下)

    这篇文章继续讨论Android事件分发机制,首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View和子 ...

  3. Android事件分发机制(上)

    Android事件分发机制这个问题不止一个人问过我,每次我的回答都显得模拟两可,是因为自己一直对这个没有很好的理解,趁现在比较闲对这个做一点总结 举个例子: 你当前有一个非常简单的项目,只有一个Act ...

  4. [转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

    Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分 ...

  5. Android事件分发理解

    Android事件分发机制是个难点和重点,结合下各家,写点自己的理解.. 首先抛出一个小问题,写一个button的点击事件 button.setOnClickListener(new OnClickL ...

  6. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  7. 【转】Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9153761 记得在前面的文章中,我带大家一起从源码的角度分析了Android中Vi ...

  8. 【自己定义控件】android事件分发机制

    自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了.滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等.或许我们第一反应就是百度,google去搜索下答案 ...

  9. Android 事件分发机制具体解释

    很多其它内容请參照我的个人网站: http://stackvoid.com/ 网上非常多关于Android事件分发机制的解释,大多数描写叙述的都不够清晰,没有吧来龙去脉搞清晰,本文将带你从Touch事 ...

随机推荐

  1. poj2513--并查集+欧拉路+字典树

    经典好题,自己不知道哪里错了交上去是RE,可能是数组开的不好吧,字典树老碰到这种问题.. 先马上别人的代码,有空对拍看看 #include <cstdio> #include <cs ...

  2. Spring Boot如何使用Runner实现启动时调用?用法和原理都在这里

    在日常的项目开发中经常会遇到这样的需求:项目启动的时候进行一些一次性的初始化工作,如读取加载资源文件.或者执行其它外部程序. 这个时候我们就可以用到spring-boot为我们提供的一种扩展机制--R ...

  3. 安装Mycat 曾经踩的那些坑

    1. INFO | jvm | ----/--/-- --:--:-- | Caused by: io.mycat.config.util.ConfigException: schema TEST d ...

  4. ActiveSync之HTTP

    Exchange ActiveSync:HTTP协议让客户端能够同步存储在服务器上的数据. 互联网工程工作小组(IETF)要求所有互联网协议都比支持UTF-8编码.因此,ActiveSync传输所使用 ...

  5. mybatis + oracle insert clob,出现ORA-01461:仅能绑定要插入LONG列的LONG值

    在网上查了很久,有可能问题是出现在当从dual中取数据时,会将clob对象的字段转为Long型 最后的解决方法用到了Begin和end语法: 1.用到begin 和end 2.用到insert int ...

  6. views.py视图函

    views.py视图函数来自 urls 的映射关系 常用所需模块 from django.shortcuts import render # ****** 渲染 render 跳转到指定的 url.h ...

  7. tomcat启动成功但是访问方面都是404

    1.开发环境与错误情况 开发环境是jdk1.7+maven+git+spring MVC+spring+mybatis+mysql. 楼主做小例子的时候发现,tomcat成功启动,但是访问主页,页面提 ...

  8. thinkphp5分页传参

    $name = input('get.searchKey/s'); if($name != ""){ $this->assign('searchKey', $name); $ ...

  9. es6 模板字符串

    模板字符串 提供构造字符串的语法糖,在 Prel/python 等语言中也都有类似特性. 1.反引号模板,可以换行 2.反引号模板,可以嵌套 用+``来嵌套 好处:语法更加简洁 var name=&q ...

  10. 【bzoj3717】[PA2014]Pakowanie 状压dp

    题解: 自己在这一类问题上想到的总是3^n的枚举法 首先背包从大到小排序 f[i]表示搞出为i的状态至少要用几个背包,g[i]表示最大剩余容量 这样就可以2^n*n 因为这么做利用了状态之间的先后顺序 ...