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 ...
随机推荐
- js消息框
<script> function del(obj, id) { layer.confirm('是否要删除信息!', { btn: ['确定', '取消'] }, function (in ...
- vue中怎样实现 路由拦截器
vue中怎样实现 路由拦截器(当用户没有登录的时候,跳转到登录页面,已经登录的时候,不能跳转到登录页,除非后台token失效) 在 我们需要实现这样 一个功能,登录拦截 其实就是 路由拦截,首先在定义 ...
- SQL语句注意得问题
1/不要使用count(列明)或count(常量)来替代count(*),count(*)是SQL92定义得标准统计行数得语法,跟数据库无关,跟NULL和非NULL无关. 说明:count(*)会统计 ...
- python jieba分词(添加停用词,用户字典 取词频
中文分词一般使用jieba分词 1.安装 pip install jieba 2.大致了解jieba分词 包括jieba分词的3种模式 全模式 import jieba seg_list = jieb ...
- [frontend] 根据文字长度 自适应宽度 自适应高度+ Uncaught ReferenceError: xxx is not defined at HTMLDivElement.onclick
CSS一行代码就可以解决第一个问题: 1.1 根据文字长度,自适应标签宽度 解决方法:把width的设置删掉,加一行代码 display:table; .tag-footdetail{ /*widt ...
- C#第三节课(2)
运算符 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.T ...
- 【Leetcode】【简单】【169求众数】【JavaScript】
题目 169. 求众数 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [ ...
- 10.使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件(转)
出处:http://www.cnblogs.com/lichenwei/p/4145696.html Mybatis属于半自动ORM,在使用这个框架中,工作量最大的就是书写Mapping的映射文件,由 ...
- .net 单元测试
都说测试驱动开发,但是想写好单元测试其实不容易,不是因为测试用例难以构造,而是因为很多时候方法非常复杂 其中部分测试想要完成就十分费力,其中让人崩溃的地方主要如下: 实例私有函数 实例静态私有函数 十 ...
- mysql查询昨天 一周前 一月前 一年前的数据
mysql 昨天 一周前 一月前 一年前的数据 这里主要用到了DATE_SUB, 参考如下 代码如下: SELECT * FROM yh_contentwhere inputtime>DATE_ ...