Android View事件分发与传递
在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定义了三种方法:
- dispatchTouchEvent()函数:负责分发传递事件,通常不把逻辑处理放在该方法中,所以一般都return super.dispatchTouchEvent().
- onInterceptTouchEvent()函数:负责拦截事件
- 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事件分发与传递的更多相关文章
- Android View 事件分发机制 源码解析 (上)
一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...
- android view事件分发机制
首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志 ...
- Android View事件分发-从源码分析
View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...
- Android View 事件分发机制 源代码解析 (上)
一直想写事件分发机制的文章,无论咋样,也得自己研究下事件分发的源代码.写出心得~ 首先我们先写个简单的样例来測试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个M ...
- Android View 事件分发机制详解
想必很多android开发者都遇到过手势冲突的情况,我们一般都是通过内部拦截和外部拦截法解决此类问题.要想搞明白原理就必须了解View的分发机制.在此之前我们先来了解一下以下三个非常重要的方法: di ...
- 浅谈Android View事件分发机制
引言 前面的文章介绍了View的基础知识和View的滑动,今天我们来介绍View的另一个核心知识,View的事件分发机制. 点击事件的传递规则 所谓的点击事件的分发机制,其实就是对MotionEven ...
- android View事件分发机制结论
原始博客有对源码的分析:http://blog.csdn.net/lmj623565791/article/details/39102591 结论:1.view事件的分发流程: dispatchTou ...
- 谈谈我对Android View事件分发的理解
写这篇博客的缘由.近期因为项目中用到相似一个LinearLayout中水平布局中,有一个TextView和Button,然后对该LinearLayout布局设置点击事件.点击TextView能够触发该 ...
- Android之事件分发机制
本文主要包括以下内容 view的事件分发 viewGroup的事件分发 首先来看两张图 在执行touch事件时 首先执行dispatchTouchEvent方法,执行事件分发. 再执行onInterc ...
随机推荐
- (转)Bootstrap 之 Metronic 模板的学习之路 - (1)总览
https://segmentfault.com/a/1190000006673582#articleHeader0 写在前面 bootstrap 的模板非常多,Envato 上有着各种各样的免费及付 ...
- php多进程防止出现僵尸进程
对于用PHP进行多进程并发编程,不可避免要遇到僵尸进程的问题. 僵尸进程是指的父进程已经退出,而该进程dead之后没有进程接受,就成为僵尸进程(zombie)进程.任何进程在退出前(使用exit退出) ...
- C#第十二节课
数组 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Th ...
- 【JavaScript游戏开发】JavaScript+HTML5封装的苏拉卡尔塔游戏(包含源码)
/** 苏拉克尔塔游戏 * 思路: * 1.棋盘设置:使用HTML5的canvas标签绘制整个棋盘 * 2.点击事件:当页面被点击时,获取点击的x,y像素点,根据此像素点进行判断,再在合适位置绘制黑红 ...
- Centos 修改主机名称
Centos 配置主机名称: 1.首先查询一下当前的主机名称 [root@localhost~]# hostnamectl status Static hostname: ****** //永久主机名 ...
- 面试官问你如何解决web高并发这样回答就好了
所谓高并发,就是同一时间有很多流量(通常指用户)访问程序的接口.页面及其他资源,解决高并发就是当流量峰值到来时保证程序的稳定性. 我们一般用QPS(每秒查询数,又叫每秒请求数)来衡量程序的综合性能,数 ...
- 数位dp题集
题集见大佬博客 不要62 入门题,检验刚才自己有没有看懂 注意一些细节. 的确挺套路的 #include<bits/stdc++.h> #define REP(i, a, b) for(r ...
- 只允许一个 <configSections> 元素。它必须是根 <configuration> 元素的第一个子元素- HTTP Error 500.19
这还是我第一次遇到这个错误,以前都没太注意配置文件中元素的放置顺序.这次在调试一个ASP.NET MVC项目的时候,突然就爆出HTTP Error 500.19错误,提示无法访问请求的页面,因为该页的 ...
- HDU 2415 Bribing FIPA
Bribing FIPA Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original I ...
- 在tomcat上全手工部署Servlet3.0
从头写java文件的方式,编译成CLASS文件,加强对SERVLET容器的理解. 稍后试试JAR和WAR包. 文件内容(跟以前用IDE的一样): HelloServlet.java: package ...