在Android中,人们主要通过手指与系统交互。Android把所有的touch事件都被封装成MotionEvent来进行处理,其中包括了手指点击的位置,时间等信息。其事件类型主要包括:ACTION_DOWN,ACTION_UP,ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP,ACTION_CANCEL。

这些事件是有触发顺序的,下面举两个栗子:

  • 只有一个手指点击在view范围内,依次触发的事件:手指按下ACTION_DOWN→手指移动ACTION_MOVE→手指抬起ACTION_UP
  • 多个手指点击在view范围内,依次触发的事件:第一根手指按下ACTION_DOWN→随后的手指按下ACTION_POINTER_DOWN→有手指抬起ACTION_POINTER_UP→最后一根手指抬起ACTION_UP。

为了处理这些事件,Android定义了三种方法:

  1. dispatchTouchEvent()函数:负责分发传递事件,通常不把逻辑处理放在该方法中,所以一般都return super.dispatchTouchEvent().
  2. onInterceptTouchEvent()函数:负责拦截事件
  3. onTouchEvent()函数和 OnTouchListener监听:负责消费和处理事件

事件传递流程

当一个事件被触发,事件的传递从Activity.dispatchTouchEvent()开始,一直从最外层的父view开始向里面的子view传递,直到被拦截。在传递过程中,view可以通过onInterceptTouchEvent()函数进行拦截,一旦父view拦截了该事件,则不再向下传递。

如果被触发的事件被传递至最内层的view,一直未被拦截消费,则会反向向外传递,这时候父view可以通过onTouchEvent函数对事件进行消费,直到activity。另外,如果被触发的ACTION_DOWN事件在某一层未被消费,那么接下来的事件是无法被传递进来的。

下面我们来看几个例子:

Case 1  手指点击在view上,父View(ViewGroup)和View都不消费事件,最终返回给activity消费。

以ACTION_DOWN事件为例,ACTION_DOWN事件沿着图中黑色箭头逐层传递。在开发过程中,我们通常会为view或者viewGroup设置监听器来捕获view事件,listener的onTouch方法会在onTouchEvent之前执行。在分发传递过程中,无论哪个方法返回true,都表示传递停止;如果返回false,则表示继续传递下去。

从图上可以看出,ACTION_DOWN事件经过activity—>ViewGroup—>View—>ViewGroup—>activity一直未被ViewGroup和View消费处理,又回到了activity中。那么随后的ACTION_MOVE和ACTION_UP事件只会沿着绿色箭头传递,不再沿着ACTION_DOWN事件的路线传递了。

Case 2  手指点击在父View和子View之间的空隙中,并未点击在子View上。同上一个例子一样,ViewGroup中并未消费该事件,返回给了activity。

这里用户并未点击到ViewGroup中的view,而是点击在了ViewGroup和View之间的空隙处。同上一个例子相同,ViewGroup并未处理ACTION_DOWN事件,而是返回给了activity处理。

Case 3  单击view后,在view中处理消费了ACTION_DOWN事件。

从图上可以看到,ACTION_DOWN事件沿着黑色箭头方向逐层向内部传递,直到在view的onTouchEvent中消费了该事件,并返回true表示不再向下传递。随后的事件ACTION_MOVE和ACTION_UP将会沿着绿色箭头传递,直到到达view的onTouchEvent方法。

Case 4  单击view,但是并不在view中处理ACTION_DOWN事件,而是让它传递到ViewGroup中处理。

ACTION_DOWN事件经过ViewGroup,ViewGroup并未拦截而是传递给View。View并未消费该事件而是回传给了ViewGroup,在ViewGroup中消费该事件。

Case 5  单击view,在ViewGroup中拦截ACTION_DOWN事件并消费

ACTION_DOWN事件沿着黑色箭头分发传递,在ViewGroup中对它进行拦截(返回true),所以就不再继续向view传递ACTION_DOWN事件了。然后在ViewGroup的onTouchEvent方法中消费了该事件,并返回true表示事件已消费。随后的ACTION_MOVE和ACTION_UP事件将沿着绿色箭头传递,直抵最后的消费方法onTouchEvent,而并不经过拦截事件。

Android View事件分发与传递的更多相关文章

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

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

  2. android view事件分发机制

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

  3. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

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

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

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

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

  6. 浅谈Android View事件分发机制

    引言 前面的文章介绍了View的基础知识和View的滑动,今天我们来介绍View的另一个核心知识,View的事件分发机制. 点击事件的传递规则 所谓的点击事件的分发机制,其实就是对MotionEven ...

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

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

  8. 谈谈我对Android View事件分发的理解

    写这篇博客的缘由.近期因为项目中用到相似一个LinearLayout中水平布局中,有一个TextView和Button,然后对该LinearLayout布局设置点击事件.点击TextView能够触发该 ...

  9. Android之事件分发机制

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

随机推荐

  1. UNIX SOCKET编程简介

    1  .  Layered Model of Networking Socket  编程的层次模型如下图所示,   最上面是应用层,应用层下面的是  SOCKET API  层,再下面是传输层和网络层 ...

  2. js-undefinde的一点延伸

    前面写过一篇js中变量定义的问题:Js中判断变量存不存在的问题 本文再补充下,变量声明未初始化的情况,代码: <script> var a; alert(a==undefined)//tr ...

  3. [转载]windows下github 出现Permission denied (publickey).解决方法

      今天在学习github的时候遇到了一些问题,然后爬了一会,找到了解决方法记录下来,以防忘记,当然能帮助别人最好啦! github教科书传送门:http://www.liaoxuefeng.com/ ...

  4. 定位IO瓶颈的方法,iowait低,IO就没有到瓶颈?

    通过分析mpstat的iowait和iostat的util%,判断IO瓶颈 IO瓶颈往往是我们可能会忽略的地方(我们常会看top.free.netstat等等,但经常会忽略IO的负载情况),今天给大家 ...

  5. TFS代码迁移Git

    描述 将TFS上的代码迁移到Git做版本控制. 参考地址 tfs-git下载:https://github.com/git-tfs/git-tfs/releases chocolatey安装:http ...

  6. POJ 1625

    什么鬼,真的是有负数的吗?我在字符加上了128才过了.dp[i][j],经过i步到达j状态的路径数.转移很容易了,建个trie图就可以,由前一步可连通到和更新即可. 另外,要用到大数和AC自动机DP ...

  7. Spark MLlib LDA 基于GraphX实现原理及源代码分析

    LDA背景 LDA(隐含狄利克雷分布)是一个主题聚类模型,是当前主题聚类领域最火.最有力的模型之中的一个,它能通过多轮迭代把特征向量集合按主题分类.眼下,广泛运用在文本主题聚类中. LDA的开源实现有 ...

  8. OC中使用UI自己定义控件实现计算器的设计(版本号1简单的加减乘除,连加,连减,连除,连乘)

    OC中使用UI自己定义控件实现计算器的设计(版本号1简单的加减乘除,连加.连减,连除,连乘) #import <UIKit/UIKit.h> @interface ViewControll ...

  9. UVAlive 6560 - The Urge to Merge(状压dp)

    LA 6560 - The Urge to Merge option=com_onlinejudge&Itemid=8&page=show_problem&problem=45 ...

  10. 利用 Gearman 实现系统错误报警功能

    Gearman 是什么? Gearman是一个用来把工作委派给其他机器.分布式的调用更适合做某项工作的机器.并发的做某项工作在多个调用间做负载均衡.或用来在调用其它语言的函数的系统. Gearman ...