前言

  在自定义组件的时候少不了会去处理一些事件相关的东西,关于事件这块网上有很多文章,有说的对的也有说的不对的,我在理解的时候也有过一段时间的迷惑,现在把自己理解的东西写下来,给有相同疑问的朋友提供些思路。
    事件呢,分为两个大的链条,一个是事件分发链条,一个是事件处理链条。分发链条是由外至内,也就是从父到子,父节点先收到并有权决定是否继续分发;而事件处理链条则是由内至外,即先由最内部的子节点处理事件,子节点有权决定是由自己来处理事件,还是抛给父节点。

概念解释

  onTouchEvent
    Implement this method to handle touch screen motion events.
    此接口是用来处理事件的,如果返回true则代表已处理,返回false则代表未处理

  onInterceptTouchEvent
    Implement this method to intercept all touch screen motion events。
    此接口是用来拦截事件的,如果返回true则代表已拦截,那么就不会再向子对象传递(本身的onTouchEvent函数依然可以处理),返回false,代表未拦截。

  This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any point.
    此接口允许你监控事件分发给子对象的过程,并且可以在任何点上获取此事件的所有权。
    Using this function takes some care, as it has a fairly complicated interaction with View.onTouchEvent(MotionEvent), and using it requires implementing that method as well as this one in the correct way. Events will be received in the following order:
     用这个功能的时候需要小心一点儿,因为这个对View.onTouchEvent(MotionEvent)有适当的影响。并且用他的时候需要实View.onTouchEvent(MotionEvent),中的正确的方法。事件按照下面的顺序被获取:

  1、You will receive the down event here
        获取down事件
      2、The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle;
        这个down事件有可能会被这个Group中的任何一个子对象处理掉,或者被自身的onTouchEvent() 方法处理掉。
         this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it)
        这就意味着你必须实现onTouchEvent()方法并且返回true,只有这样你才能够看到其余的手势动作(而不是找一个父view来处理他)
         Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
        同时,如果 onTouchEvent()返回为true,你也不会接收到 onInterceptTouchEvent()中其余的事件并且所有的事件处理必须像onTouchEvent() 一样正常处理。
     3、For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().  
        随着你返回了false,那么接下来的事件(up事件)会被先传到这个接口里,然后传给它的 onTouchEvent().  
     4、If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
         此时如果你返回了true,你就不会再接收到其余的事件,目标view也会接收除了ACTION_CANCEL外也和它一样的事件。其余的事件会被传递到onTouchEvent() 方法中,并不会出现在此接口中。

事件关系

  以上两个事件接口的解释内容是从api中翻译下来的。接下来就看ViewGroup和View的事件传递关系
      1、ViewGroup和View都有onTouchuEvent事件
      2、ViewGroup有onInterceptTouchEvent事件。

  通过上面概念的分析我们知道了,onInterceptTouchEvent使用来控制事件传递的,是从父对象向子对象传递。onTouchuEvent是进行事件处理,它是由子对象向父对象进行冒泡,也就是说如果子对象处理了该事件(返回true),那么就不在向父对象传递了,父对象的onTouchEvent就收到down事件(以及以后的事件)了,
     如果子对象处理不了该事件(返回false)那么该事件就会冒泡给父对象的onTouchEvent,如果此时父对象处理了(返回true),那么子对象也就无法处理以后的事件了;由onInterceptTouchEvent来决定是否对该事件进行拦截,如果事件在此处被拦截了,那么onTouchEvent就没有机会再去处理了。

  比如,有以下的布局,并且在view上进行了一次点击。

<cn.bitlove.test.CLayout android:id="@+id/layout" >
<cn.bitlove.test.CView android:id="@+id/view" />
</cn.bitlove.test.CLayout>

  那么down事件首先被Layout的onInterceptTouchEvent事件接收,如果拦截(返回true)了,那么子对象的onTouchuEvent不会收到任何接下来的事件了,但是Layout自身的onTouchEvent依然可以处理;
     如果未拦截,那么子对象的onTouchEvent就可以处理了,如果子对象的onTouchEvent函数处理的事件(返回true),那么父对象的onTouchEvent就没有机会再处理了。

  如果子对象的onTouchEvent对象没有处理该事件(返回false),那么将交由父对象进行处理,之后的事件子对象无法控制。之后如果父对象处理了down事件,那么由父对象继续处理后续事件,如果父对象也没有处理这个down事件,那么继续向他的父对象继续冒泡该事件,如果都没有处理,那么整个事件链结束。

总结

  可以这么说,touch事件事件链(donw->move->up),他由两个过程组成,一是事件的分发,二是事件的处理。先处理事件的分发,这个分发主要影响子对象,如果事件的分发被打断了,子对象自然没有后续的处理了。
    事件的处理,是由子对象向父对象冒泡,谁从哪个事件点接手处理,谁就接手之后的整个事件链条,当然他也可以处理一些环节后,继续把后续的事件链交由父对象处理。需要注意的是,一旦事件链交出去后就没有机会再处理了,比如子对象处理完down事件后不想处理move事件,把move事件交由父对象处理, 等父对象处理完再由自己继续处理up事件,这样是不行的。事件链控制权总是向父对象冒泡,不能往回。

后记

  把握住事件的两个链条,那么对事件的理解就清晰很多了

ViewGroup 和 View 事件传递及处理小谈的更多相关文章

  1. Android View事件传递机制

    ViewGroup dispatchTouchEvent onInterceptTouchEvent onTouch View dispatchTouchEvent onTouch 假设View的层级 ...

  2. 公共技术点( View 事件传递)

    转载地址:http://p.codekk.com/blogs/detail/54cfab086c4761e5001b253e 本文为 Android 开源项目源码解析 公共技术点中的 View 事件传 ...

  3. View事件传递之父View和子View之间的那点事

    Android事件传递流程在网上可以找到很多资料,FrameWork层输入事件和消费事件,可以参考: Touch事件派发过程详解 这篇blog阐述了底层是如何处理屏幕输,并往上传递的.Touch事件传 ...

  4. Android的View 事件传递

    欢迎转载,请附出处: http://blog.csdn.net/as02446418/article/details/47422891 1.基础知识 (1) 全部 Touch 事件都被封装成了 Mot ...

  5. View的绘制、事件传递过程

    View绘制过程 onMeasure() onLayout() onDraw() 过程详解 onMeasure() 计算尺寸 onLayout() 为viewGroup类型布局子视图用的. onDra ...

  6. Android事件传递机制详解及最新源码分析——View篇

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 对于安卓事件传递机制相信绝大部分开发者都听说过或者了解过,也是面试中最常问的问题之一.但是真正能从源码角度理解具体事件传递流程的相信并不多, ...

  7. View事件分发机制

    所谓的事件分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个传递的过程就是分发过程. 点击事件的分发由3个方 ...

  8. 初识Android触摸事件传递机制

    前言 今天总结的一个知识点是Andorid中View事件传递机制,也是核心知识点,相信很多开发者在面对这个问题时候会觉得困惑,另外,View的另外一个难题滑动冲突,比如在ScrollView中嵌套Li ...

  9. Android--View事件传递

    Android--View事件传递 View事件传递首先要明白以下要素: 事件就是MotionEvent.该对象包含了传递的事件中的所有信息 事件的来源是Window(即PhoneWindow),包含 ...

随机推荐

  1. rsyncd.conf 文件

    uid = nobodygid = nobodymax connections = 10timeout = 60use chroot = noread only = falsepid file=/va ...

  2. 有向无环图(DAG)的最小路径覆盖(转)

    DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如 ...

  3. [kuangbin带你飞]专题十一 网络流

            ID Origin Title   34 / 81 Problem A POJ 3436 ACM Computer Factory   92 / 195 Problem B POJ 3 ...

  4. hibernate one-to-many many-to-one 双向注解

    建表语句: DROP TABLE IF EXISTS `t_company`; CREATE TABLE `t_company` ( `companyId` ) unsigned NOT NULL A ...

  5. 查看用户的SQL执行历史

    程序开发少不来SQL,基本都是基于SQL开发,程序仅仅起一个流程控制的作用.但是数据库本身存在许多内置的视图或者内置的表,如果打算研究SQL执行的效率已经SQL执行的历史记录,通过这些视图可以知道. ...

  6. OC基础(6)

    getter/setter方法 点语法 Self关键字 Super关键字 *:first-child { margin-top: 0 !important; } body > *:last-ch ...

  7. How to deploy JAVA Application on Azure Service Fabric

    At this moment, Azure Service Fabric does not support JAVA application natively (but it's on the sup ...

  8. dll 学习(一)

    DLL(Dynamic Link Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了"无库-静态链接库-动态链接库 ...

  9. JAVA编写WEB服务器

    一.超文本传输协议  1.1 HTTP请求  1.2 HTTP应答  二.Socket类  三.ServerSocket类  四.Web服务器实例  4.1 HttpServer类  4.2 Requ ...

  10. 学习练习 java20160507作业

    第一题 求水仙花的个数: //求水仙花数 int zongshu = 0; for(int i =100; i<=999;i++) { int bai = i/100; //求百位上面的数字 i ...