前言

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

概念解释

  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. C# String.Format大全 去 decimal 后面的 0

    转 http://kwon.iteye.com/blog/1068255  http://blog.csdn.net/tvvbbb/article/details/47256943 public st ...

  2. 手机端的各种默认样式比如 ios的按钮变灰色

    1.ios按钮变灰色,给按钮加样式: -webkit-appearance: none; 2.有圆角话 ; } 3.去除Chrome等浏览器文本框默认发光边框 input:focus, textare ...

  3. SAP_20140304

    1.  SAP 主打产品  R/3 :分布式 客户端/服务器 环境的标准ERP软件. 2. 主要功能模块:销售和分销,物料管理,生产计划,质量管理,工厂维修,人力资源,工业方案,办公室和通信,项目系统 ...

  4. Problem 2195 检查站点(普通树构造)(Vector)

    Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 在山上一共有N个站点需要检查,检查员从山顶出发去各个站点进行检 ...

  5. sqlite报错OutOfMemory

    如 java.sql.SQLException: out of memory at org.sqlite.DB.throwex(DB.java:252) at org.sqlite.NestedDB. ...

  6. Android——拖动条SeekBar

    1.activity_seekbar.xml <?xml version="1.0" encoding="utf-8"?><LinearLay ...

  7. cocos2d-x 中添加显示文字的三种方式 LabelTTF 、LabelBMFont 和 LabelAtlas

    在 cocos2d-x 中有三个类可以在层或精灵中添加文字: LabelTTF LabelBMFont LabelAtlas LabelTTF 直接支持使用 TTF 字库,可以支持全部的中文,但是效率 ...

  8. DP最长递增字符串

    对于最简单DP问题,比如7 9 1 10 3中最长的递增字符串就是7 9 10,所以长度是3. 对于这个问题,就是从第二个开始,让后面的每一个字符都假设作为咱们要找的最长的字符串的最后一个字符,然后从 ...

  9. jmeter做接口测试

    jmeter做接口测试有两种方式: 1. 2.

  10. Golang在windows下交叉编译linux程序

    1.下载相关程序. Golang下载:http://www.golangtc.com/download Git下载:http://git-scm.com/download/ TDM-GCC下载:htt ...