Android基础学习(二十二)—— View的事件分发(1)

news2025/1/16 5:46:41

一、View的层级关系

二、View的事件分发机制

1、MotionEvent ——点击事件

点击事件用MotionEvent来表示

  • ACTION_DOWN:手指刚接触屏幕

  • ACTION_MOVE:手指在屏幕上移动

  • ACTION_UP:手指从屏幕上松开的一瞬间

点击事件的事件分发,就是对MotionEvent事件的分发过程,即当一个MotionEvent产生了以后,系统需要把这个事件传递给一个具体的View,这个传递过程就是分发过程。

2、事件分发机制——点击事件的传递规则

    一次完整的事件分发过程会包括三个阶段,即事件的发布、拦截、消费。这三个阶段分别对应声明在View和ViewGroup中的三个方法,即dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent。注意,View不包含onInterceptTouchEvent方法。

(1)Touch事件如何从屏幕到达APP

用户触摸屏幕/按键操作
	硬件驱动收到事件,将触摸事件包装为Event存到/dev/input/event[x]目录下
		SystemServer进程中的InputManagerService负责与硬件通信,接受屏幕输入事件,内部的读线程InputReader会从系统的/dev/input/目录拿到任务,并分发给InputDispatcher线程

App进程的主线程监听socket客户端,收到输入事件
	NativeInputEventReceiver.handleEvent
		InputEventReceiver.dispatchInputEvent【即-->】
			ViewRootImpl.WindowInputEventReceiver.dispachInputEvent
				ViewRootImpl.WindowInputEventReceiver.onInputEvent
					ViewRootImpl.enqueueInputEvent

(2)Touch事件到达APP后怎么传递到对应页面

ViewRootImpl.enqueueInputEvent(InputEvent event, InputEventReveiver receiver, int flags, boolean processImmediately)
	ViewRootImpl.doProcessInputEvent()
		ViewRootImpl.deliverInputEvent(QueuedInputEvent q)  //注1  见下一篇文章
			InputStage.deliver(QueuedInputEvent q) //注2  见下一篇文章
                ViewPostImeInputStage.onProcess
        			ViewPostImeInputStage.processPointerEvent
            			DecorView.dispatchPointerEvent
                			DecorView.dispatchTouchEvent

(3)事件在Activity、Window、DecorView中的传递

在Activity、PhoneWindow、DecorView中,最先接收到触摸事件的是DecorView

DecorView.dispatchTouchEvent
	Activity.dispatchTouchEvent
		PhoneWindow.superDispatchTouchEvent
			DecorView.superDispatchTouchEvent
				ViewGroup.dispatchTouchEvent  //DecorView调用其父类的方法,本质上还是在DecorView内部调用

在这里插入图片描述

img

1)事件没被拦截、事件被消费

ViewGroup没拦截ACTION_DOWN事件且有View消费该事件:

//假设当前已经递归到了 DecorView
//ACTION_DOWN事件 ACTION_DOWN事件
DecorView.dispatchTouchEvent  //即ViewGroup.dispatchTouchEvent
	DecorView.onInterceptTouchEvent  //没拦截 
	DecorView.dispatchTransformedTouchEvent
		... ...
			MyViewgroup.dispatchTouchEvent   
				MyViewgroup.onInterceptTouchEvent  //没拦截 
				MyViewgroup.dispatchTransformedTouchEvent
					MyView.dispatchTouchEvent  
						MyView.onTouchEvent   //return true
					MyView.dispatchTouchEvent  //return true
				MyViewgroup.dispatchTransformedTouchEvent //true
					newTouchTarget=mFirstTouchTarget=MyView
			MyViewgroup.dispatchTouchEvent  //return true
	   ... ...
	DecorView.dispatchTransformedTouchEvent  //true 
	   	newTouchTarget=mFirstTouchTarget=child  //child为DecorView中被touch的那个子ViewGroup
DecorView.dispatchTouchEvent 

ACTION_MOVE、ACTION_UP的事件分发过程同上

2)没被拦截、没被消费

如果底层View不消费,则默认一步步往上执行父元素onTouchEvent方法。
如果所有View的onTouchEvent方法都返回false,则最后会执行到Activity的onTouchEvent方法,事件分发也就结束了。

ACTION_DOWN事件:

DecorView.dispatchTouchEvent
	Activity.dispatchTouchEvent
		PhoneWindow.superDispatchTouchEvent
			DecorView.superDispatchTouchEvent
				ViewGroup.dispatchTouchEvent  //DecorView
					ViewGroup.onInterceptTouchEvent  //没拦截 
					ViewGroup.dispatchTransformedTouchEvent(child)
						...
						MyViewgroup.dispatchTouchEvent   
							MyViewgroup.onInterceptTouchEvent  //没拦截 
							MyViewgroup.dispatchTransformedTouchEvent(child)
								MyView.dispatchTouchEvent  
									MyView.onTouchEvent   //return false
								MyView.dispatchTouchEvent  //return false
							MyViewgroup.dispatchTransformedTouchEvent(child) //false
							MyViewgroup.dispatchTransformedTouchEvent(null)
                            	View.dispatchTouchEvent
                            		View.OnTouchEvent   //return false    调用OnTouchEvent 
						MyViewgroup.dispatchTouchEvent  //return false
						...
					ViewGroup.dispatchTransformedTouchEvent(child)  //return false
					ViewGroup.dispatchTransformedTouchEvent(null)
						View.dispatchTouchEvent
                        View.OnTouchEvent   //return false   调用OnTouchEvent   
				ViewGroup.dispatchTouchEvent   //return false
			DecorView.superDispatchTouchEvent   //return false
		PhoneWindow.superDispatchTouchEvent   //return false
	Activity.dispatchTouchEvent
		Activity.onTouchEvent   //return false  调用OnTouchEvent 
DecorView.dispatchTouchEvent

ACTION_MOVE、ACTION_UP事件:

DecorView.dispatchTouchEvent
	Activity.dispatchTouchEvent
		PhoneWindow.superDispatchTouchEvent
			DecorView.superDispatchTouchEvent
				ViewGroup.dispatchTouchEvent  //DecorView  注意不再执行拦截判断(ACTION_DOWN 或 mFirstTouchTarget!=null 时才走)
					ViewGroup.dispatchTransformedTouchEvent(child:null)
						View.dispatchTouchEvent
							View.OnTouchEvent  //return false   在DecorView中调用一次OnTouchEvent  
						View.dispatchTouchEvent  //return false
					ViewGroup.dispatchTransformedTouchEvent(child:null) //return false
				ViewGroup.dispatchTouchEvent  //return false
			DecorView.superDispatchTouchEvent   //return false
		PhoneWindow.superDispatchTouchEvent   //return false
	Activity.dispatchTouchEvent
		Activity.onTouchEvent  //在Activity中调用一次OnTouchEvent  
DecorView.dispatchTouchEvent

3)被拦截

① 被拦截、被消费

如果 ViewGroup 自身拦截且消费了 ACTION_DOWN 事件,即 onInterceptTouchEvent 和 onTouchEvent 两个方法均返回了 true,那么本次事件序列的后续事件就都会交由其进行处理(如果能接收得到的话),在设置拦截的那个ViewGroup中不会再调用其 onInterceptTouchEvent 方法来判断是否进行拦截

ACTION_DOWN事件:

DecorView.dispatchTouchEvent
	Activity.dispatchTouchEvent
		PhoneWindow.superDispatchTouchEvent
			DecorView.superDispatchTouchEvent
				ViewGroup.dispatchTouchEvent
					ViewGroup.onInterceptTouchEvent  
					ViewGroup.dispatchTransformedTouchEvent(child)
						MyViewGroup.dispatchTouchEvent
							MyViewGroup.onInterceptTouchEvent  //true 被拦截
							MyViewGroup.dispatchTransformedTouchEvent(null)
								View.dispatchTouchEvent
									View.OnTouchEvent  //return true   
								View.dispatchTouchEvent  //return true
							MyViewGroup.dispatchTransformedTouchEvent(null)   //return true
						MyViewGroup.dispatchTouchEvent  //return true
					ViewGroup.dispatchTransformedTouchEvent(child) //return true
							newTouchTarget=mFirstTouchTarget=MyViewGroup  //给mFirstTouchTarget赋值
				ViewGroup.dispatchTouchEvent  //return true
			DecorView.superDispatchTouchEvent   //return true
		PhoneWindow.superDispatchTouchEvent   //return true
	Activity.dispatchTouchEvent  //return true
DecorView.dispatchTouchEvent	

ACTION_MOVE、ACTION_UP事件:

DecorView.superDispatchTouchEvent
	ViewGroup.dispatchTouchEvent
		ViewGroup.onInterceptTouchEvent
		ViewGroup.dispatchTransformedTouchEvent(child)
			MyViewGroup.dispatchTouchEvent   //MyViewGroup在ACTION_MOVE、ACTION_UP事件中就不再拦截了 因为执行到这里时mFirstTouchTarget=null
                MyViewGroup.dispatchTransformedTouchEvent(null)
                    View.dispatchTouchEvent
                        View.OnTouchEvent  //return true   
                    View.dispatchTouchEvent  //return true
                MyViewGroup.dispatchTransformedTouchEvent(null)   //return true
            MyViewGroup.dispatchTouchEvent  //return true
        ViewGroup.dispatchTransformedTouchEvent(child) //return true
    ViewGroup.dispatchTouchEvent  //return true
DecorView.superDispatchTouchEvent   //return true  

② 被拦截、没有被消费

而如果 ViewGroup 拦截了 ACTION_DOWN 事件,但是 onTouchEvent 方法中又没有消费掉该事件的话,那么本次事件序列的后续事件都不会再被其接收到,而是直接交由父视图进行处理。




参考文章:

一文读懂 View 事件分发机制

解决这 8 个问题,Android事件分发再往前一步

看一遍就忘不了,事件分发机制分析——dispatchTouchEvent

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/93948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OM6621系列国产M4F内核低功耗BLE5.1大内存SoC蓝牙芯片

目录OM6621系列简介OM6621P系列芯片特性应用领域OM6621系列简介 随着5G与物联网时代的到来,智慧城市、电动出行、智能家居、可穿戴设备等应用高速发展,低功耗蓝牙技术在近几年智能化浪潮中的地位也尤为重要。OM6621系列的开发即是为解决国内低功耗蓝牙应…

Linux安装docker 保姆级教程

一、docker介绍 Docker 是 2014 年最为火爆的技术之一,几乎所有的程序员都听说过它。Docker 是一种“轻量级”容器技术,它几乎动摇了传统虚拟化技术的地位,现在国内外已经有越来越多的公司开始逐步使用 Docker 来替换现有的虚拟化平台了。 二…

图为科技深圳人工智能产业协会重磅推出边缘计算机全新概念

人工智能作为提升区域竞争力的重要战略,全国各地都在推动发展,人工智能是未来科技创新发展的风向标,也是产业变革升级的关键驱动力,我国在《“十四五”数字经济发展规划》及《工业互联网创新发展行动计划(2021-2023年)》中&#x…

Linux基础(4)-进程管理

该文章主要为完成实训任务,详细实现过程及结果见【参考文章】 参考文章:https://howard2005.blog.csdn.net/article/details/127066383?spm1001.2014.3001.5502 文章目录一、查看进程1. 进程查看命令 - ps2. Liunx进程状态3. 观察进程变化命令 - top4. …

b站黑马的Vue快速入门案例代码——【axios+Vue】天知道(天气信息查询功能)

目录 目标效果: 更换的新接口接口文档: 天知道新的Get请求接口:http://ajax-api.itheima.net/api/weather html文件中注意因为接口更换,要修改原代码为如下红字部分: 重点原理: (1)v-on可以…

环形链表问题

文章目录环形链表问题1.环形链表题干思路延申问题总结2. 环形链表 II题干思路环形链表问题 环形链表就是一个链表没有结束的位置,链表的最后一个节点它会指向链表中的某一个节点形成一个环。 拿力扣的两到题目来看 1.环形链表 题干 给你一个链表的头节点 head …

JavaScript JSON解析

最近在uniapp中遇到了一个bug,排查后是json解析的问题。对uniapp开发比较熟悉的,应该会知道uni.navigateTo 这个API方法。这是官方提供用于跳转页面的方法。 有时候我们在跳转页面时会想传递一些参数,通常采用这样的方式 navigateTo(url, r…

oauth2.0--基础--6.1--SSO的实现原理

oauth2.0–基础–6.1–SSO的实现原理 1、什么是SSO 1.1、概念 在一个 多系统共存 的环境下,用户在一处登录后,就不用在其他系统中登录,就可以访问其他系统的资源。用户环境 浏览器:只能同一个浏览器,不会出现A浏览器…

zabbix部署【各模块超详细】

目录 安装zabbix 部署zabbix 配置zabbix 1. 修改语言 2. 监控linux端 3. 修改中文乱码 报警功能 报警音报警 邮件报警 脚本报警 邮件通知内容 图形模块 创建图形 创建聚合图形 percona mysql模板 nginx模板 克隆主机 网络发现 自动注册 主被动模式 🍁如果对你有帮助…

Handsontable复制列标题内容的功能

Handsontable复制列标题内容的功能 添加了通过使用3个新的上下文菜单选项复制列标题内容的功能:“使用标题复制”、“使用组标题复制”和“仅复制标题”。 添加了4个用于以编程方式复制列标题的新API方法:“copyCellsOnly()”、“copyWithColumnHeaders(…

vscode jupyter配置远程服务器开发

背景说明:本地vscode中使用jupyter编写本地python代码很方便,各种快捷键用的飞起。但是要做线上大数据分析时。在集群环境中搭建一个jupyter。使用网页端编写程序非常不习惯,所以想到能不能将线上的jupyter接口开出来,使用vscode远…

js-有关时间

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date 有关Date 返回格式 Sun Oct 10 2021 00:00:00 GMT0800 (中国标准时间) new Date() 无参数 获取当前时间new Date(value) 传入时间戳 传入一个时间戳 一个 Unix 时间戳(U…

JVM运行流程/运行时数据区

JVM运行流程 程序在执行之前先要把 java代码 转换成 字节码文件 (.class文件), JVM 首先需要把字节码通过一定的方式 类加载器 (ClassLoader) 把文件加载到内存中 运行时数据区 (Runtime Data Area) , 而字节码文件是 JVM 的一套指令集规范, 并不能直接交给底层操作系统去执行…

【大数据技术Hadoop+Spark】Hive数据仓库架构、优缺点、数据模型介绍(图文解释 超详细)

一、Hive简介 Hive起源于Facebook,Facebook公司有着大量的日志数据,而Hadoop是实现了MapReduce模式开源的分布式并行计算的框架,可轻松处理大规模数据。然而MapReduce程序对熟悉Java语言的工程师来说容易开发,但对于其他语言使用…

Anaconda为虚拟环境安装第三方库与Spyder等软件的方法

本文介绍在Anaconda中,为Python的虚拟环境安装第三方库与Spyder等配套软件的方法。 在文章Anaconda中Python虚拟环境的创建、使用与删除(https://blog.csdn.net/zhebushibiaoshifu/article/details/128334614)中,我们介绍了在Anac…

提前做好网络安全分析,运维真轻松(二)

背景 某汽车总部已部署NetInside流量分析系统,使用流量分析系统提供实时和历史原始流量。汽车配件电子图册系统是某汽车集团的重要业务系统。本次分析重点针对汽车配件电子图册系统进行预见性分析,以供安全取证、性能分析、网络质量监测以及深层网络分析…

FRP搭建内网穿透

前言 内网穿透方式很多,可以用公网IP进行端口映射,DDNS等。现在我有个云服务器,使用它做中转作为内网穿透的工具。 可以在这个网址了解下原理基础:内网穿透工具的原理与开发实战 FRP内网穿透 FRP是一个内网穿透的反向代理应用…

电压放大器工作原理及特点是什么

很多人虽然经常使用电压放大器,但是对于电压放大器的工作原理以及特点是什么都不清楚,下面就来为大家讲解。 什么是电压放大器? 电压放大器是一种能够增加信号电压的装置。对于弱信号,通常采用多级放大级联方式分直接耦合、阻容耦…

关于机器人状态估计(10)-VSLAM与VIO的3D建图,重定位与世界观综述

近期我国迎来了cov海啸,其实我也不知道我羊了没有,但并没有什么不舒服同时因为我没有测,那自然是没有羊,或者是薛定谔的羊。 近年另外一块工作的综述,这篇科普的同时,也会包含部分有价值的信息。 一. 摘要…

【面试题】 面试官:你如何实现大文件上传

大厂面试题分享 面试题库 前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 一、问题分析 如果将大文件一次性上传,会发生什么?想必都遇到过在一个大文件上传、转发等操作时,由…