【View系列】View事件分发源码探索,安卓常见面试题知乎

Android面试题精选:讲一讲-Android-的事件分发机制 本来写到这就结束了,但回顾一遍还是打算给大家稍微总结一下。需要总结的小点:1、Android 事件分发总是遵循 Activity => ViewGroup => View 的传递顺序;2、onTouch()执行总优先于onClick()Android事件分发机制详解:史上最全面、最易懂,所以直接引用一下其中的图片。Activity 的事件分发示意图ViewGroup 事件分发示意图View 的事件分发示意图事件分发工作流程总结。 阅读详情

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

…

//actionDown是一系列事件的开头 需要重置所有状态

if (actionMasked == MotionEvent.ACTION_DOWN) {

cancelAndClearTouchTargets(ev);

resetTouchState();

}

final boolean intercepted;

//如果是down事件 或者mFirstTouchTarget不为空

if (actionMasked == MotionEvent.ACTION_DOWN

|| mFirstTouchTarget != null) {

//如果子类并没有调用parent.requestDisallowInterceptTouchEvent(true) 那么这个值为false

final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;

//如果子类调用了requestDisallowInterceptTouch(true) 则这个if判断条件不成立 反之则会进去

if (!disallowIntercept) {

//进入viewGroup的onInterceptTouchEvent()方法 默认返回false

intercepted = onInterceptTouchEvent(ev);

ev.setAction(action); // restore action in case it was changed

} else {

intercepted = false;

}

} else {

//如果没有子view消费了事件 并且事件不是down事件 intercepted 为true

intercepted = true;

}

…

//如果没有cancel而且viewGroup本身也没拦截事件 则进入这个代码块

if (!canceled && !intercepted) {

…

//如果事件是down事件 则进入代码块

if (actionMasked == MotionEvent.ACTION_DOWN

|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)

|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {

…

final int childrenCount = mChildrenCount;

if (newTouchTarget == null && childrenCount != 0) {

…

final View[] children = mChildren;

//倒序遍历child查看child 是否消费了事件

for (int i = childrenCount - 1; i >= 0; i–) {

…

//child.canReceivePointerEvents() 标识child是否能接收触摸事件 判断条件是可见并且没有执行动画

//!isTransformedTouchPointInView(x, y, child, null) 用来判断触摸事件的x,y 是否在child的矩形区域内

//两个判断有一个条件不满足就会遍历下一个child

if (!child.canReceivePointerEvents()|| !isTransformedTouchPointInView(x, y, child, null)) {

continue;

}

…

//调用子view的dispatchTouchEvent 在view的dispatchTouchEvent里面调用了onTouchEvent()

//如果子view消费了事件 则dispatchTransformedTouchEvent()返回true 进入代码块执行逻辑

if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {

…

//赋值newTouchTarget

//addTouchTarget()方法会将mFirstTouchTarget赋值 方便下面的事件系列直接拿到 //mFirstTouchTarget.child并调用其dispatchTouchEvent方法

newTouchTarget = addTouchTarget(child, idBitsToAssign);

//将其设置为true 下面代码会用到

alreadyDispatchedToNewTouchTarget = true;

break;

}

}

…

}

}

if (mFirstTouchTarget == null) {

// mFirstTouchTarget == null 代表没有子view消费事件

// 如果没有子view消费事件那么以后则直接调用dispatchTransformedTouchEvent方法 结果实际上是直接调用自己的onTouchEvent()

// 注意 第三个参数出的是null 会直接调用到super.dispatchTouchEvent()即view的dispatchTouchEvent()

//view的dispatchTouchEvent会调用onTouchEvent

handled = dispatchTransformedTouchEvent(ev, canceled, null,

TouchTarget.ALL_POINTER_IDS);

} else {

//如果mFirstTouchTarget不为null(代表有子view消费了事件) 则走进这个代码块

TouchTarget predecessor = null;

TouchTarget target = mFirstTouchTarget;

while (target != null) {

final TouchTarget next = target.next;

//down事件的时候如果有子view消费事件了 alreadyDispatchedToNewTouchTarget值会为true 并且

//target和newTouchTarget地址值是一样的

if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {

handled = true;

} else { //其他事件(除了down)都会走这个代码块

//如果viewGroup拦截了事件 则会导致cancelChild为true 此时传递子view的event.action 是ACTION_CANCEL

final boolean cancelChild = resetCancelNextUpFlag(target.child)

|| intercepted;

//继续调用子view的dispatchTouchEvent

//注意第三个参数这时候传的是target.child 并不是null 内部会target.child.dispatchTouchEvent()

if (dispatchTransformedTouchEvent(ev, cancelChild,

target.child, target.pointerIdBits)) {

handled = true;

}

//如果取消child事件

//那么会导致mFirstTouchTarget = target.next

//通常单指事件cancelChild 直接会导致mFirstTouchTarget为null

if (cancelChild) {

if (predecessor == null) {

mFirstTouchTarget = next;

} else {

predecessor.next = next;

}

//回收target

target.recycle();

target = next;

continue;

}

}

predecessor = target;

target = next;

}

}

return handled;

}

public boolean onInterceptTouchEvent(MotionEvent ev) {

…

return false;

}

private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,

View child, int desiredPointerIdBits) {

…

if (child == null) {

//调用view的dispatchTouchEvent

handled = super.dispatchTouchEvent(transformedEvent);

else {

…

//调用子view的dispatchTouchEvent

handled = child.dispatchTouchEvent(transformedEvent);

}

return handled;

}

//View.java

//View 的dispatchTouchEvent

public boolean dispatchTouchEvent(MotionEvent event) {

…

//首先查看是否设置有onTouchListener 如果有并且返回了true 则不会执行onTouchEvent

//下面的代码说明onTouchListener优先级高于onTouchEvent

ListenerInfo li = mListenerInfo;

if (li != null && li.mOnTouchListener != null

&& (mViewFlags & ENABLED_MASK) == ENABLED

&& li.mOnTouchListener.onTouch(this, event)) {

result = true;

}

if (!result && onTouchEvent(event)) {

result = true;

}

…

return result;

}

public boolean onTouchEvent(MotionEvent event) {

…

//标识view是否可点击 设置onClickListener也会导致clickable为true

final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE

|| (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)

|| (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;

if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {

switch(action) {

case MotionEvent.ACTION_UP:

…

//回调了OnClickListener的onClick方法

performClickInternal();

…

break;

}

//如果view可点击 直接就返回true了

return true;

}

//如果view不可点击 返回false

return false;

}

复制代码

通过上面的源码分析,我们可以总结一下基础流程:

  • 首先ACTION_DOWN事件:

  • 刚开始我们会清除之前的所有touch状态,因为ACTION_DOWN 是一系列事件的开头

  • 然后我们会询问自己的onInterceptTouchEvent方法 是否拦截事件 默认不拦截


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

如果不拦截 倒序遍历children,让每个子view 调用自己的dispatchTouchEvent方法**

  • 子view 处理过程中分为:

  • 子view消费了事件 那么我们会赋值mFirstTouchTarget对象 并将alreadyDispatchedToNewTouchTarget置为true 接着执行下面的代码块:

if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {handled = true; }

然后返回handled;

  • 子view没消费事件或者是viewGroup自己拦截了 那么mFirstTouchTarget对象为空 直接走进去dispatchTransformedTouchEvent()并在里面调用了自己的onTouchEvent方法,然后返回handled;

  • 后序事件(以ACTION_MOVE为例):

  • 再次进来的时候 分为两种情形:

  • 如果mFirstTouchTarget不为空(说明有子view消费了事件),我们先走viewGroup的onInterceptTouchEvent方法询问viewGroup自己是否拦截事件,接着走到了

if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) {handled = true;}

还是间接调用了child的dispatchTouchEvent方法

  • 如果mFirstTouchTarget为空,直接走进去dispatchTransformedTouchEvent()并在里面调用了viewGroup自己的onTouchEvent方法,并且以后自己的子view都不会接收到任何其他事件系列。
Android面试题精选:讲一讲 Android 的事件分发机制 面试场景 讲讲 Android 的事件分发机制? 基本会遵从 Activity => ViewGroup => View 的顺序进行事件分发,然后通过调用onTouchEvent()方法进行事件的处理。我们在项目中一般会对MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP,MotionEvent.ACTION_MOVE,Moti... 阅读详情

相关推荐

【Android 自定义 View】-->事件分发机制

定义 将点击事件(MotionEvent)传递到某个具体的View & 处理的整个过程。

Kevin Learn Android 495

【View系列】View事件分发源码探索

Override//actionDown是一系列事件的开头 需要重置所有状态//如果是down事件 或者mFirstTouchTarget不为空= null) {//如果子类并没有调用parent.requestDisallowInterceptTouchEvent(true) 那么这个值为false= 0;//如果子类调用了requestDisallowInterceptTouch(true) 则这个if判断条件不成立 反之则会进去if (!

xcbyaya的博客 1070

Android 面试:事件分发8连问,安卓基础面试题

当屏幕被触摸,Linux内核会将硬件产生的触摸事件包装为Event存到/dev/input/event[x]目录下 这样做的目的是将输入事件封装为通用的Event,供后续处理 [](()1.2 SystemServer部分 我们知道,当系统启动时,在SystemServer进程会启动一系列系统服务,如AMS,WMS等 其中还有一个就是我们管理事件输入的InputManagerService 这个服务就是用来负责与硬件通信,接受屏幕输入事件。 在其内部,会启动一个读线程,也就是InputReader,它会从系

m0_54851114的博客 527

Android面试题精选:讲一讲-Android-的事件分发机制,架构师必备

本来写到这就结束了,但回顾一遍还是打算给大家稍微总结一下。需要总结的小点:1、Android 事件分发总是遵循 Activity => ViewGroup => View 的传递顺序;2、onTouch()执行总优先于onClick()Android事件分发机制详解:史上最全面、最易懂,所以直接引用一下其中的图片。Activity 的事件分发示意图ViewGroup 事件分发示意图View 的事件分发示意图事件分发工作流程总结。

2401_83974087的博客 2540

神经元细胞结构刨析(持续更新)

神经细胞的学习笔记

weixin_46596227的博客 2222

RT-Thread与ROS2通信:micro-ROS在STM32上的移植实践

本文详细介绍了在STM32平台上使用RT-Thread实时操作系统移植micro-ROS实现与ROS2通信的实践方案。通过对比rosserial方案,重点阐述了micro-ROS基于XRCE-DDS协议栈在数据可靠性(丢包率低于1%)、双模式通信(UDP/串口)以及C/C++混合编程方面的优势,为嵌入式设备与ROS2的高效通信提供了完整解决方案。

emacs5lisp的博客 332

安卓自定义View进阶-事件分发机制详解

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。【Android思维脑图(技能树)】知识不体系?

2301_79963818的博客 708

无人机芯片模块技术要点分析

恶劣环境下信号稳定性:无人机在恶劣环境下工作时,遥感系统采集的信号往往很不稳定,视频信号处理芯片需要具备强抗干扰能力,能辨别脉冲脉宽为50ns以上、幅度为0V~4.5V的输入信号。这种架构能兼顾强大的运算能力和灵活的接口控制。芯片小型化:麻省理工学院的研究人员已设计出仅20平方毫米的微型芯片,可处理无人机飞行所需的惯性数据和相机图像,为微型无人机的发展奠定了基础。光子集成芯片(PIC) :研究显示,与电子芯片相比,光子计算芯片在延迟、计算容量和能效上都有数量级的提升,有望解决当前无人机系统的计算瓶颈。

YUNZHUO666的博客 1404

Android View 事件分发机制

本场chat主要分享从源码掌握android中关于view的事件分发机制,充分了解事件分发机制有助于了解平时开发中view事件滑动冲突的原因以及解决方法,同时这个知识点也是面试中被问到的概率较大的面试题,接下来就一起来看下它的庐山真面目吧...

GitChat 340

中国银行信息科技岗位笔试

收到笔试只剩四天了,收集的资料,后续会更新

weixin_46050242的博客 4596

两张 300I Duo 部署 Qwen3.5‑32B

开发者成功使用两张华为300IDuo(共4颗Ascend310P3芯片)部署Qwen3/Qwen3.5的30B/32B模型,并公开详细步骤。关键点包括:硬件需两张300IDuo(每芯片44GB显存),软件需CANN≥24.1和MindIE2.3.0专用镜像。部署流程涵盖驱动安装、模型下载(需修改为FP16格式)、容器启动、张量并行配置(TP=4)等环节。实测显示每芯片显存占用20-35GB,系统稳定运行。该方案已在知乎等平台验证可行,适用于Qwen3.5-32B等同类模型。

evering的博客 2257

Android面试必问,事件分发机制

事件分发机制不仅仅是核心知识点更是难点,并且还是View的一大难题滑动冲突解决方法的理论基础,因此掌握好View的事件分发机制是十分重要的。事件分发的对象是点击事件(Touch事件),而当用户触摸屏幕时,将产生点击事件。

Fantasy 3092

基于STM32设计的遥控小车(手机APP+GPS+温湿度+ESP8266)

一、环境介绍 小车主控MCU: STM32F103ZET6 STM32程序开发IDE: keil5 STM32程序风格: 采用寄存器方式开发,注释齐全,执行效率高,方便移植 手机APP: 采用QT设计,程序支持跨平台编译运行(Android、IOS、Windows、Linux都可以编译运行,对应平台上QT的环境搭建,之前博客已经发了文章讲解) 硬件包含: 淘宝购买的完整一套4轮遥控小车(采用STM32F103ZET6作为主控板)、DHT11温湿度传感器、中科微GPS模块、ESP8266 ...

6万+

android事件分发机制

Android View事件分发机制的核心流程是:触摸事件从Activity开始,经由Window和DecorView,层层传递给根ViewGroup。ViewGroup通过dispatchTouchEvent()分发事件,用onInterceptTouchEvent()决定是否拦截,若不拦截则传递给子View。子View通过onTouchEvent()处理事件,返回true则消费事件,false则回溯给父容器。整个过程遵循"谁返回true谁消费事件"的规则,最终决定事件的流向和处理。

琦琦的博客 1201

Xilinx平台SRIO介绍(五)示例工程Example Design介绍

理解IP的使用,少不了Example Design的学习。

数字IC/FPGA杂货铺,找一找,或许有你想要的~ 1万+

孔雀优化算法(POA)详解:从孔雀智能到优化引擎

孔雀优化算法(POA)是一种新型元启发式优化算法,灵感来源于孔雀的社会行为和智能狩猎策略。该算法将孔雀群体分为雄孔雀、雌孔雀和幼孔雀三个阶层,分别对应全局探索、平衡搜索和局部开发三种搜索策略。通过模拟孔雀的求偶展示、自适应接近和Levy飞行等行为,POA实现了探索与开发的动态平衡。算法采用角色分配机制和位置更新方程,结合参数自适应调整,展现出优于传统算法的全局搜索能力和收敛性能。POA已成功应用于多个优化问题,其生物启发机制为解决复杂优化问题提供了新思路。

qq_42212808的博客 137

安卓自定义View进阶-事件分发机制详解,Android高级工程师进阶学习】

A: 我们知道 View 可以注册很多事件监听器,例如:单击事件(onClick)、长按事件(onLongClick)、触摸事件(onTouch),并且View自身也有 onTouchEvent 方法,那么问题来了,这么多与事件相关的方法应该由谁管理?单击事件(onClickListener) 需要两个两个事件(ACTION_DOWN 和 ACTION_UP )才能触发,如果先分配给onClick判断,等它判断完,用户手指已经离开屏幕,黄花菜都凉了,定然造成 View 无法响应其他事件,应该最后调用。

2401_84007049的博客 869

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

第三章:View事件分发机制

伪代码总结下} else {onInterceptTouchEvent方法和onTouchEvent方法都是在dispatchTouchEvent方法中执行。分发事件入口是Activity,然后是PhoneWindow,然后是DecorView,最后传递给顶层的ViewGroup。

friday1110的博客 830

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

android View事件分发和事件拦截

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。用来事件的分发,如果事件能够传递给当前的View,那么此方法一定会被调用,返回的结果受到当前View的onTouchEvent和下级的dispatchTouchEvent方法的影响。在dispatchTouchEvent方法中调用,用来处理点击的事件,返回结果是否消耗当前事件,如果不消耗,如果不消耗,则在同一个事件的序列中,当前View无法再次接收到事件。

2401_84009215的博客 790

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android Touch事件分发(源码分析),阿里巴巴Android面试题答案

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。面试过程一定要有礼貌!

2401_83627805的博客 865

玩转Android事件分发机制

当一个点击事件发生时,从Activity的事件分发开始(),流程总结如下:流程总结主要包括:dispatchTouchEvent()、onTouchEvent() 总结如下那么,ViewGroup的什么时候返回truefalse?请继续往下看ViewGroup事件的分发机制流程2: ViewGroup的事件分发机制。

2401_84121789的博客 672

C++ 实习面试第一阶段:面向对象基础

C 和 C++ 都是通用编程语言,但设计思想和语言特性有所不同。C++ 相比 C 增加了以下重要特性:面试回答: C++ 并不是完全取代 C 的语言,它兼容了大量 C 语言的编程方式,同时提供了面向对象、泛型编程和资源管理等更丰富的特性。指针是存储对象地址的变量,引用是对象的别名。代码示例: 需要注意:两者都用于表示空指针,但类型和使用方式不同。为什么引入 nullptr?因为 NULL 在一些实现中本质上是整数 0,可能导致函数重载时产生歧义。 面试重点: C++11 以后优先使用 nullptr

zengjiajun2006的博客 1133
上一篇: 【Java转Android】60,作为一个程序员你觉得最大的悲哀是什么
下一篇: 【中级—,kotlin教程
flunsna
博客等级 码龄5年 10粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值