ViewGroup 和 View 事件传递及处理小谈

前言

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

概念解释

  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事件,这样是不行的。事件链控制权总是向父对象冒泡,不能往回。

后记

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

时间: 2024-11-08 19:05:31

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

View 事件传递

公共技术点之 View 事件传递 本文为 Android 开源项目源码解析 公共技术点中的 View 事件传递 部分 分析者:Trinea,校对者:Trinea,校对状态:完成 本文后面后继续整理. 推荐一篇我看到的对传递机制介绍最清楚的国外文章吧.本文略作翻译. 1.基础知识 (1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置.时间.历史记录以及第几个手指(多指触摸)等. (2) 事件类型分为 ACTION_DOWN, ACTION_UP, AC

android事件传递机制的浅谈

想必大家有时会遇到需要自定义控件吧,这个时候就会遇到事件的传递和处理了,非常繁琐啊!百度上面一大票关于事件的传递机制,但是都千篇一律,都是dispatchTouchEvent 返回true,则事件被拦截,false则分发给子控件之类的,经过几天的研究发现这个事件传递并没有说的这么简单也没有想象中的难. 一般的点击事件.滑动事件都是用ACTION_UP.ACTION_MOE.ACTION_DOWN组成的,android应用里面默认情况下,触摸事件是从activity开始传递,假设里面的view都不

View 事件传递,分发与拦截

1.基础知识 (1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置.时间.历史记录以及第几个手指(多指触摸)等. (2) 事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束. (3) 对事件的处理包括三类,分别为传递--dispatchT

Android的View 事件传递

欢迎转载,请附出处: http://blog.csdn.net/as02446418/article/details/47422891 1.基础知识 (1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置.时间.历史记录以及第几个手指(多指触摸)等. (2) 事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,

委托、事件、匿名的小谈

有一段时间我在写异步方法的时候碰到了异步调用同步控件的问题,那时候我找到很多的都是关于委托的相关资料,但是那时候我并不是特别明白. 委托到底是什么?为什么会出现? 这个问题,虽然现在不是很了解,但至少我已经找到了一个理解的办法. 先从定义一个委托出发: public delegate string Trans(string a) 这是一个委托,它也和方法.函数的定义一样,具有自己的签名,以及返回值声明.如果有读者又不理解的,我希望是回头看看语法书上的说明,这里 就不多阐述. 我们先看一个实例:

Android ViewGroup 触摸事件传递机制

引言 上一篇博客我们学习了Android View 触摸事件传递机制,不了解的同学可以查看Android View 触摸事件传递机制.今天继续学习Android触摸事件传递机制,这篇博客将和大家一起探讨ViewGroup的触摸事件传递机制. 示例 示例代码如下: public class MainActivity extends ActionBarActivity { private String TAG = "MainActivity"; private MyViewGroup pa

深入理解 View 的事件传递机制

引言:现在 GitHub 上酷炫的 Android 控件越来越多,一方面我们可以让 App 各美观,另一方面我们这些开发者也可以从中学习到各种知识.写下这篇博文主要是记录研究自定义控件源码过程中接触到的知识盲区,帮助自己巩固知识的同时,也和大家交流学习,一起进步. Demo源码 废话不多说,进入正题: 一.概述 View 事件传递机制 用户通过点击.滑动屏幕与 App 产生交互是移动互联网时代的交互基础,那么在 Android 中,用户的点击.滑动是怎么和 Android 系统产生交互的呢? 在

View的绘制、事件传递过程

View绘制过程 onMeasure() onLayout() onDraw() 过程详解 onMeasure() 计算尺寸 onLayout() 为viewGroup类型布局子视图用的. onDraw() 执行绘制图形动作. View事件传递 Touch事件封装在MotionEvent对象中,其中包括touch的位置.时间.历史记录以及第几个手指触摸(多点触摸)等. Touch事件分为: ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_D

对touch事件传递的简单理解

对View事件传递的理解,看的这篇. 对事件传递有了大致的了解.onInterceptTouchEvent 函数决定是否将事件拦截,拦截之后,该控件的所有子控件接收不到这个事件.onTouchEvent 函数判断是否消费此事件,在父控件把事件传递到子控件的过程中,假设都没有拦截,那么消息会传递到底层控件,底层控件可以选择消费或者不消费,如果消费,那么事件到此终止,如果没有消费,则一层一层传递给父类.如果中途被拦截了,那么拦截的那个控件充当上述过程的底层控件.最重要的,在这个过程中,事件所经过的控