引言

  前面的文章介绍了View的基础知识和View的滑动,今天我们来介绍View的另一个核心知识,View的事件分发机制。

点击事件的传递规则

  所谓的点击事件的分发机制,其实就是对MotionEvent事件的分发过程,当一个MotionEvent产生以后,系统需要把这个事件传递给一个具体的View,这个传递的过程就是分发过程。点击事件的分发主要由三个很重要的方法来共同完成的,它们是:dispatchTouchEvent、onInterceptTouchEvent和OnTouchEvent。下面我们一一介绍这些方法。

  public boolean dispatchTouchEvent(MotionEvent event)

  用来进行事件的分发。如果事件能够传递给当前的View,这个方法是一定会被调用的,返回结果受到当前View的OnTouchEvent和下级View的dispatchTouchEvent方法的影响,返回值表示是否消耗当前事件(true消耗)。

  public boolean onInterceptTouchEvent(MotionEvent ev)

  这个方法是在上面一个方法的内部调用的,用来判断是否拦截某个事件。如果当前View拦截了某一个事件,那么在同一个事件序列中,此方法不会被再次调用,返回结果表示是否拦截当前的事件。

  public boolean onTouchEvent(MotionEvent event)

  在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。

  那么上面3个方法到底有什么区别呢?下面我们用一段伪代码来表述:

  上面的代码已经很清晰的表达了3者之间的关系,通过上面的代码我们大致可以知道点击事件的传递规则:对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,这时候它的dispatchTouchEvent就会被调用。这个时候会有两种情况:

  第一种情况:如果这个ViewGroup的onInterceptTouchEvent方法返回true就表示它需要拦截当前事件,接着事件就会交给这个ViewGroup处理,就是它的onTouchEvent方法会被调用。

  第二种情况:如果这个ViewGroup的onInterceptTouchEvent方法返回false就表示它不需要拦截当前事件,这时这个事件就会继续传递给它的子元素,接着子元素的dispatchTouchEvent就会被调用,如此反复直到事件被最终处理。

  注意点:

  当一个View需要处理事件时,如果设置了OnTouchListener,那么OnTouchListener中的onTouch方法会被调用。这时候事件如何处理还是需要看onTouch方法的返回值。这时候又分成两种情况:

  第一种情况:如果onTouch方法返回false,那么当前View的onTouchEvent方法会被调用;

  第二种情况:如果onTouch方法返回true,那么当前View的onTouchEvent方法不会被调用,处理逻辑会在OnTouch方法中完成。

  通过这个逻辑我们知道,给View设置的OnTouchListener优先级要比onTouchEvent方法要高。在onTouchEvent方法中,如果我们设置有OnClickListener,那么它的onClick方法会被调用。我们可以看出平时我们常用的OnClickListener其优先级最低,处于事件传递的末端。

简单的总结归纳

  当一个点击事件产生以后,它的传递过程遵循如下顺序Activity-->Window-->View。即事件总要先传递给Activity,然后在传递给Window,最后Window在传递给顶级的View。顶级的View接收到事件后,就会按照事件分发机制去分发事件。

  关于事件传递机制,这里给出一些结论,根据这些结论可以更好的理解整个事件传递机制。

  1、同一个事件序列是指从手指触摸屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程中所产生的一系列事件,这个事件序列以down事件开始,中间含有数量不定的move事件,最后以up事件结束。

  2、某一个View一旦决定拦截,那么这一事件序列都只能由他来处理(如果事件序列可以传递给它),并且它的onInterceptTouchEvent不会再被调用。我们可以这样理解这段描述,就是当一个View决定拦截一个事件后,系统会把同一个事件序列中的其他都事件都直接交给他处理,不需要再调用View的onInterceptTouchEvent去询问是否需要拦截。

  3、正常情况下,一个事件序列只能被一个View拦截且消耗。原因第二条已经说的很清楚了。

  4、某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent方法返回false),那么同一个事件序列中的其他事件都不会再交给他处理,并且事件将重新交给它的父元素去处理,即父元素的onTouchEvent方法会被调用。意思就是:事件一旦交给一个View去处理,那么它就必须消耗掉,否则同一个事件序列中剩下的事件不会再交给它处理。

  5、如果View不消耗除ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续接收到后续的事件,最终这些消失的点击事件会传递给Activity处理。

  6、ViewGroup默认不会拦截任何事件,Android源码中ViewGroup中的onInterceptTouchEvent方法默认方法false。

  7、View没有dispatchTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法会被调用。

  8、View的onTouchEvent默认会消耗事件(返回true),除非它是不可点击的(clickable和longClickable都是false)。View的longClickable属性默认都是false,click属性要分情况,Button的clickable属性默认是true,TextView的clickable默认是false。不过设置OnClickListener会将clickable设置为true。

  9、onClick会发生的前提是当前View是可点击的,并且受到down和up的事件。

  11、事件传递的过程总是由外向内的,事件总是先传递给父元素,然后再有父元素分发给子View。通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外。

  下篇文章我们来从源码的角度来解析View的事件分发机制。

浅谈Android View事件分发机制的更多相关文章

  1. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  2. android view事件分发机制

    首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志 ...

  3. Android View 事件分发机制 源代码解析 (上)

    一直想写事件分发机制的文章,无论咋样,也得自己研究下事件分发的源代码.写出心得~ 首先我们先写个简单的样例来測试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个M ...

  4. Android View 事件分发机制详解

    想必很多android开发者都遇到过手势冲突的情况,我们一般都是通过内部拦截和外部拦截法解决此类问题.要想搞明白原理就必须了解View的分发机制.在此之前我们先来了解一下以下三个非常重要的方法: di ...

  5. android View事件分发机制结论

    原始博客有对源码的分析:http://blog.csdn.net/lmj623565791/article/details/39102591 结论:1.view事件的分发流程: dispatchTou ...

  6. Android之事件分发机制

    本文主要包括以下内容 view的事件分发 viewGroup的事件分发 首先来看两张图 在执行touch事件时 首先执行dispatchTouchEvent方法,执行事件分发. 再执行onInterc ...

  7. Android面试必问!View 事件分发机制,看这一篇就够了!

    在 Android 开发当中,View 的事件分发机制是一块很重要的知识.不仅在开发当中经常需要用到,面试的时候也经常被问到. 如果你在面试的时候,能把这块讲清楚,对于校招生或者实习生来说,算是一块不 ...

  8. Atitit View事件分发机制

    1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTo ...

  9. android的事件分发机制理解

    android的事件分发机制理解 1.事件触发主要涉及到哪些层面的哪些函数(个人理解的顺序,可能在某一层会一次回调其它函数) activity中的dispatchTouchEvent .layout中 ...

随机推荐

  1. UE和UI的区别

    UI:User Interface的缩写,是指用户界面,最普遍的应用是在软件开发中,主要是指程序的用户操作界面的设计,随着Web应用的普及,UI也应用在了Web的用户界面规划上了.网站用户界面(Web ...

  2. 高性能Android应用开发

  3. Windows平台编译SQLite 3

    由于需要sqlite的x64版本只能自己编译,下载sqlite源代码.sqlite.def.Visual Studio 2013新建一个Visual C++ Empty Project,Configu ...

  4. 【CF739E】Gosha is hunting 贪心

    [CF739E]Gosha is hunting 题意:有n个小精灵,你有a个普通球和b个超级球,用普通球抓住第i只小精灵的概率为$A_i$,用超级球抓住第i只小精灵的概率为$u_i$.你必须一开始就 ...

  5. Gradle 教程

    extends:http://www.zhihu.com/question/27866554/answer/38427122 stormzhang博客精华 有一个Gradle 的教程,足够你入门啦. ...

  6. C# XML对象序列化、反序列化

    XML 序列化:可以将对象序列化为XML文件,或者将XML文件反序列化为对象还有种方法使用LINQ TO XML或者反序列化的方法从XML中读取数据. 最简单的方法就是.net framework提供 ...

  7. Java与JS判断请求来是否来自移动端

    Java public boolean JudgeIsMoblie(HttpServletRequest request) { boolean isMoblie = false; //String[] ...

  8. logstash实战input插件syslog

    vim /etc/logstash/conf.d/syslog.conf input{ syslog{ type => "system-syslog" port => ...

  9. windows10安装ubuntu16.04双系统

    因为科研需要,主要在ubuntu系统中进行学习开发,介绍一下安装windows10下安装ubuntu的经验. 1.工具 u盘(或者你也可以在你的硬盘中分出一部分FAT32的硬盘空间) Easyuefi ...

  10. OC中分类(Category)和扩展(Extension)

    1.分类的定义 category是Objective-C 2.0之后添加的语言特性,中文也有人称之为分类.类别.Category的主要作用是为已经存在的类添加方法.这个大家可能用过很多,如自己给UIC ...