安卓触摸事件分发机制分析

Android下的Touch事件分发详解 本文详细解析了Android的Touch事件分发机制,包括三个核心方法:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent的作用和调用过程,以及事件的传递路径。文章还深入探讨了ViewGroup中dispatchTouchEvent方法的实现,为读者提供了全面的理解和应用触摸事件分发机制的指南。 阅读详情

1. 前言

🎯 一句话总结:

触摸事件(TouchEvent)会从 Activity 层开始,按从外到内的方式传递给每一个 ViewGroup/View,直到某个 View 消费(consume) 它,事件传递就会停止。

📌 事件分发三个关键方法

方法名所在类作用说明
dispatchTouchEvent()所有 View/ViewGroup事件分发入口,决定是否继续向下传递
onInterceptTouchEvent()仅 ViewGroup是否拦截事件,阻止传递给子 View
onTouchEvent()所有 View/ViewGroup事件的最终处理者(消费者)


DecorView是一个应用窗口的根容器,它本质上是一个FrameLayout。DecorView有唯一一个子View,它是一个垂直LinearLayout,包含两个子元素,一个是TitleView(ActionBar的容器),另一个是ContentView(窗口内容的容器)。

Activity.dispatchTouchEvent()
        ↓
    Window.superDispatchTouchEvent()
        ↓
    DecorView.dispatchTouchEvent()
        ↓
   ViewGroup.dispatchTouchEvent()
        ↓
    - onInterceptTouchEvent() → 是否拦截?
            ↓            ↓
       拦截自己处理     不拦截继续往下
                         ↓
        子View.dispatchTouchEvent()
          ↓
        View.dispatchTouchEvent()
            ↓
    - onTouchListener.onTouch()
   - onTouchEvent()


  • Activity.dispatchTouchEvent()
    • 触摸事件从系统层传入,Activity 先接收。
    • 通常会把事件传给当前的 DecorView(根 View)。
  1. ViewGroup.dispatchTouchEvent()
    • 尝试调用 onInterceptTouchEvent() 判断是否拦截事件。
      • 返回 true:表示当前 ViewGroup 要处理,子 View 不再收到事件。
      • 返回 false:继续把事件传给子 View。
  2. 子 View.dispatchTouchEvent()
    如果是 ViewGroup,会重复上面的流程(递归)。
    • 如果是普通 View,直接调用 onTouchEvent()。
  3. onTouchEvent()
    • 如果返回 true,表示事件被消费(消费后不会再向上传递)。
    • 如果返回 false,当前控件不处理,事件会被传回上层 ViewGroup 的 onTouchEvent()。

2. Activity、ViewGroup、View事件分发机制分析

Activity事件分发机制
  • Activity.dispatchTouchEvent(MotionEvent event)

源码(Activity.java仅关键代码):

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}
  • onUserInteraction():通知用户交互,和事件分发无关。
  • 调用 getWindow().superDispatchTouchEvent(ev):
    • Window 是 PhoneWindow。
    • PhoneWindow 把事件交给了 DecorView(一个 ViewGroup)处理。
  • 如果 superDispatchTouchEvent(ev) 返回 true,说明事件被下面消费了。
  • 否则调用 Activity.onTouchEvent(ev)(比如点击空白处)。
ViewGroup 事件分发机制

DecorView 是 ViewGroup,所以它遵循 ViewGroup 的事件分发规则。

  • ViewGroup.dispatchTouchEvent(MotionEvent ev)

源码(ViewGroup.java仅关键代码):

ViewGroup.dispatchTouchEvent 代码可大致简化为下面这个样子

public boolean dispatchTouchEvent(MotionEvent ev) {
    // 1. 是否拦截事件
    boolean intercepted = onInterceptTouchEvent(ev);

    // 2. 如果没有拦截,遍历子 View 分发
    if (!intercepted) {
        for (int i = childrenCount - 1; i >= 0; i--) {
            final View child = children[i];
            if (child.dispatchTouchEvent(ev)) {
                return true;
            }
        }
    }

    // 3. 子 View 没有消费,自己处理
    return super.dispatchTouchEvent(ev);
}

详细代码可以查看ViewGroup.dispatchTouchEvent 中 dispatchTransformedTouchEvent方法

    private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
            View child, int desiredPointerIdBits) {
        final boolean handled;

        // Canceling motions is a special case.  We don't need to perform any transformations
        // or filtering.  The important part is the action, not the contents.
        final int oldAction = event.getAction();
        if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
            event.setAction(MotionEvent.ACTION_CANCEL);
            if (child == null) {
                handled = super.dispatchTouchEvent(event);
            } else {
                handled = child.dispatchTouchEvent(event);
            }
            event.setAction(oldAction);
            return handled;
        }
        // 省略....
		    return handled;
    }
  • onInterceptTouchEvent(ev):决定是否拦截事件(默认返回 false)。
  • 如果返回 true,自己处理,不再传递给子 View。
  • 如果没有拦截,会遍历子 View,调用子 View 的 dispatchTouchEvent(ev)。
  • 如果有任何一个子 View 返回了 true,说明消费了事件,整个流程结束。
  • 如果子 View 都没有消费,最后调用自己的 super.dispatchTouchEvent(ev),即作为普通 View 处理。
View 事件分发机制

View 是最终事件的接收者。

  • View.dispatchTouchEvent(MotionEvent ev)

源码(View.java仅关键代码):

public boolean dispatchTouchEvent(MotionEvent event) {
    boolean result = false;
    
    // 1. 先判断是否需要触发 OnTouchListener
    ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnTouchListener != null
            && (mViewFlags & ENABLED_MASK) == ENABLED
            && li.mOnTouchListener.onTouch(this, event)) {
        result = true;
    }

    // 2. 如果 OnTouchListener 没消费,再走 onTouchEvent
    if (!result && onTouchEvent(event)) {
        result = true;
    }

    return result;
}

  • 优先执行 onTouchListener.onTouch()。
    • 如果返回 true,表示事件被消费,不继续往下传递。
  • 否则走 onTouchEvent(event)。

因为点击事件是在 onTouchEvent 中的 case MotionEvent.ACTION_UP: 中判断调用的,具体查看 View.performClickInternal()方法。

这里就是,如果你设置了某个 View 的 OnTouchListener 并且在 onTouch 方法中返回 true,那么这个 View 的 onClick 方法不会执行的原因。


3. 理解 ViewGroup 的递归式事件分发?

核心理解:递归式分发

  • 父 ViewGroup 收到事件,先问自己:“要不要拦截?”(onInterceptTouchEvent)**
  • 如果 不拦截,就 找出被点击的子 View
  • 然后 把事件递给子 View 的 dispatchTouchEvent() 方法
  • 子 View 又可以是一个 ViewGroup(比如 LinearLayout),于是子 View 又重复上面的流程: onInterceptTouchEvent()
  • 再分发给自己的子 View。
  • 就这样,一层一层递归下去,直到遇到一个普通 View(没有子 View 的 Button、TextView),最后交给 onTouchEvent() 来消费。

打个通俗比喻:

  • 一个 ViewGroup 就像一个"村长",负责分发任务。
  • 它收到任务(MotionEvent)后,会问:
    • 我要自己干?(拦截)
    • 还是派给手下某个小村民?(子 View)
  • 村民又是个小村长(嵌套 ViewGroup)的话,继续往下派。
  • 最后一个真正干活的是普通农民(Button/TextView)。

补充个知识点:

onInterceptTouchEvent() 只在 “ACTION_DOWN” 开始时有意义!!

  • 因为一旦一个手指 ACTION_DOWN 被拦截了,后续的 ACTION_MOVE / ACTION_UP 事件都跟着这个处理链走。
  • 如果 DOWN 没拦截,后面的 MOVE/UP 也不会随便切换到拦截。

这叫做 事件的捕获(capture)机制,Android 保证事件流动的一致性。


4. 最后

Android 事件分发是一层层向下传,遇到拦截或者消费就停;否则事件会向上传递,直到有人消费或者丢弃。

还有一个问题,对于没了解过事件分发机制的同学来说,对于事件分发:由外到内,事件消费:由内到外 的理解,可能有些困惑,包括我自己,其实就可以简单理解为 ViewGroup 一个方法把事件分发机制写完,方法中间就是挨个遍历子 View 挨个问,你要不要这个事件(由外到内),都不要的话,我就要了(又回到了 由内到外 ),带着这个理解,去看源码就很容易理解事件分发机制了。

全面解析Android事件分发机制:一篇足矣!(1) 至此,相信大家已经对Android的事件分发有了感性的认知下面,我将详细介绍Android事件分发机制2. 事件分发机制 源码分析Android事件分发流程 =即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到View从上可知,要想充分理解Android分发机制,本质上是要理解:Activity对点击事件的分发机制ViewGroup对点击事件的分发机制View对点击事件的分发机制下面,我将通过源码,全面解析事件分发机制Activity事件分发机制、 阅读详情

相关推荐

Android事件分发机制

最近在学习安卓的事件分发机制,实际上到目前为止还没有写过自定义View,在自定义View中如果需要能够响应手指的点击或者滑动事件就需要处理事件的分发,否则很容易出现冲突。写这篇博客是为了让自己能够更好的消化吸收,同时以后忘了能够很快的捡回来。此篇主要参考。

ucasyzj的博客 1963

Android touch事件分发机制★

首先先从源码的角度分析View的事件分发。 从一个简单的例子入手。比如说你当前有一个非常简单的项目,只有一个Activity,并且Activity中只有一个按钮。如果想要给这个按钮注册一个点击事件,只需要调用: button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.d(“TAG”, “onClick execute”); } }); 这样在onClick方法里面写实现,就可以

zenmela2011的专栏 2981

Android的事件分发

一、Touch事件和绘制事件的异同之处Touch事件和绘制事件很类似,都是由ViewRoot派发下来的,但是不同之处在绘制事件是由应用中的某个View发起请求,一层一层上传到ViewRoot,再有ViewRoot下发绘制,传递canvas给所有子View让其绘制自身,绘制好后,再通知WMS进行画到屏幕上。而Touch事件是由硬件捕获到触摸后由系统传递给应用的ViewRoot,再由ViewRoot往下

JackChan 2857

Android事件分发机制详解:史上最全面、最易懂

点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。这里的对象是指Activity、ViewGroup、View事件分发过程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三个方法协助完成经过上述3个问题,相信大家已经对Android的事件分发有了感性的认知,接下来,我将详细介绍Android事件分发机制。

w1142203475的博客 1万+

AndroidTouch事件传递机制解析

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:1)publicbooleandispatchTouchEvent(MotionEvent ev)这个方法用来分发TouchEvent2)publicbooleanonInterceptTouchEvent(MotionEvent

GD32F303片内FLASH实战:从地址映射到数据持久化存储

本文详细介绍了GD32F303片内FLASH的实战应用,从地址映射到数据持久化存储的全过程。通过解析FLASH的基础特性、安全操作区域规划、擦除写入读取的三重奏操作,以及工程化进阶技巧,帮助开发者高效利用片内FLASH进行数据存储。文章还提供了调试技巧和常见问题解决方案,特别适合嵌入式开发者在实际项目中应用。

weixin_26742753的博客 214

android 的触摸事件的分发拦截机制分析

今天给大家讲解一下android中触摸事件的分发拦截机制,Android为触摸事件封装了一个类,MotionEvent,如果在项目中你重写过onTouchEvent方法,你就会发现该参数就是一个MotionEvent。在MotionEvent中封装了不少比较实用的东西,比如触摸点的坐标,点击事件的类别等。这样大家就对触摸事件有了一定的了解了,现在说一下事件的拦截机制。        我们大家

gongzhiyao37390814的博客 531

一文介绍Linux EAS

EAS只在系统负载不重时,即系统中每个CPU的利用率都低于其算力的80%时才被启用,而且选出的最节能CPU只有比线程当前运行的CPU节约能量大于6%时,线程才会迁移到该CPU运行。因此EAS为线程选择最节约能量的CPU来运行的前提条件是很苛刻的,针对重载场景(比如游戏),EAS的功能应该很少被使用起来,针对重载场景的功耗优化,这里可能是一个值得尝试的点。算力(capacity)是CPU调度中的一个基础概念,它反映的是一个CPU的计算能力,是个规格化的值,可以通过读取Android手机的文件节点。

youzhangjing_的博客 1234

Android笔记:触摸事件的分析与总结----TouchEvent处理机制,事件分发处理机制

Android中的事件类型分为按键事件和屏幕触摸事件。TouchEvent是屏幕触摸事件的基础事件,要深入了解屏幕触摸事件的处理机制,就必须掌握TouchEvent在整个触摸事件中的转移和处理过程。此处将对TouchEvent处理机制的学习做个小小的总结和备记。 当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到...

Android格调小窝 720

WIFI 相关的频偏调试以及天线调试记录

WIFI RF 相关的频偏调试以及天线调试 1,频率误差(Frequency Error) 频率误差(Frequency Error):表征射频信号偏离该信号所处信道中心频率的大小,单位PPM。频偏误差要求范围如下表。 频偏越小越好。PPM的计算公式如下: 问题: 我们ESP8089认证测试的时候频偏测试超了。需要修改哪些呢。 测试频率点在2.411865385GHz 宣称点:2.412GHz 频率偏移计算:{(2.412GHz-2.411865385GHz)÷2...

armkits的博客 1万+

51单片机智能小车

最近学校举办了一个智能小车比赛,比赛内容为用手机蓝牙控制小车拥有5个功能,分别是超声波舵机避障,测距(显示在LCD1602上), 红外跟随,循迹还有蓝牙控制小车前进后退左转又转以及停止。 文章目录 蓝牙控制所有功能 一、蓝牙控制前进后退左转右转停止 二、舵机超声波避障加测距 三、红外跟随 四、循迹 五、代码部分 六、完整代码 前言 基于51单片机的智能小车是比较基础的小车,很适合初学者学习 提示:以下是本篇文章正文内容,下面案例可供参考 一、整体思路 这款小...

m0_55977420的博客 1万+

Android触摸事件分发处理机制详解与源码分析一(View篇)

出处:http://blog.youkuaiyun.com/yanbober/article/details/45887547/ Notice:阅读完该篇之后如果想继续深入阅读Android触摸屏事件派发机制详解与源码分析下一篇请点击《Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)》查看。 1 背景 最近在简书和微博还有Q群看见很多人说android自定义控件(Vi

harrain的博客 736

【学习系列】SAP RAP 3:添加多层级的子节点

本文详细介绍了在SAP ABAP RAP开发中如何创建多层级业务对象。主要内容包括:1)创建明细和计划行层级的数据库表及CDS视图;2)使用association和composition关键字建立父子关联关系;3)创建各层级的投影视图并设置层级关系;4)更新行为定义,添加关联、操作权限等控制;5)更新服务定义公开新增视图;6)创建元数据扩展优化UI展示。通过这一系列步骤,实现了从抬头到明细再到计划行的完整业务对象层级结构,为后续UI功能扩展奠定了基础。

DeveloperMrMeng的博客 587

Android MotionEvent分发机制

一、简单说一下分发机制原理 在看分发机制的时候,需要知道MotionEvent是一层一层向下分发的,通过ViewGroup的dispatchTouchEvent方法进行分发。 ViewGroup的dispatchTouchEvent方法会先调用ViewGroup的onInterceptTouchEvent方法。 如果返回true,会直接调用ViewGroup的onTouchEvent; 如

sirenyizhi的博客 768

请举手回答,LDO和DC-DC有什么不同?

文章目录1 LDO是什么2 LDO典型电路3 DC-DC是什么4 DC-DC典型电路5 LDO和DC-DC区别10.2.6 小结一下 大家好,我是记得诚。 DC-DC和LDO都是电源芯片,两者差异很大,用法也不同,这篇博客讲述LDO和DC-DC的一些差异,帮助更好的认识LDO和DC-DC并进行选型。 1 LDO是什么 LDO是low dropout regulator的简称,即低压差线性稳压器,这是相对于传统的线性稳压器来说的,传统的稳压器,输入比输出要高出很多,否则无法工作,LDO可能输入比输出高1~2V

记得诚 1万+

ANFIS实现数据非线性回归附Matlab代码

在本文中,我们将介绍如何使用Matlab实现基于MSE的ANFIS非线性回归,并提供相应的源代码。ANFIS是一种融合了模糊逻辑和神经网络的方法,它可以通过学习数据集中的模式来构建一个模糊推理系统。ANFIS的训练过程基于最小化MSE,以提高模型的拟合能力。通过上述代码示例,我们可以使用基于MSE的ANFIS模型对数据进行非线性回归,并获得相应的预测结果。在示例中,我们定义了一个包含两个样本的新输入数据集 X_new,然后使用训练好的ANFIS模型进行预测,并将结果存储在变量 Y_pred 中。

2301_79326588的博客 473

【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 六 )

Android 事件分发 系列文章目录、 一、按下触摸事件记录、 二、完整的触摸事件处理机制、 三、ViewGroup | dispatchTouchEvent 方法返回、 四、ViewGroup 事件分发相关源码、 五、View 事件分发相关源码、

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 1569

Unity 佳能SDK 及数据获取

3. 把CameraControl 下面只要是绿色的 .cs 文件都复制到Unity 中。1. 填写信息跟官方申请SDK,大概1-2个工作日会邮件回复你。2. 将SDK这两个文件放到 Unity Plugins文件夹。

我知道你很急,但是路要一步步走 1475

Android自定义控件系列九:从源码看Android触摸事件分发机制

请尊重原创劳动成果,转载请注明出处:http://blog.youkuaiyun.com/cyp331203/article/details/45071069,非允许请勿用于商业或盈利用途,违者必究。         Android触摸事件,网上也有很多文章来讲了,今天在这里想使用例子和源码相结合的方式,可能会看的更清晰一些。         在讲例子和源码之前,还是先把结论讲一下

true100的专栏 855

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Android事件分发机制(相关文章)

Android事件分发机制完全解析,带你从源码的角度彻底理解(上) http://blog.youkuaiyun.com/guolin_blog/article/details/9097463 Android事件分发机制完全解析,带你从源码的角度彻底理解(下) http://blog.youkuaiyun.com/guolin_blog/article/details/9153747 Android中...

weixin_34189116的博客 66

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

android 触摸机制,Android触摸事件传递机制

原标题:Android触摸事件传递机制前言成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~。 一、了解Activity的构成一个Activity包含了一个Window对象,这个对象是由PhoneWindow来实现的。PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是Titl...

weixin_29516495的博客 309

老版QQ原生表情gif动态

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

Android中事件分发机制详解

事件分发 分类: 事件的分发机制 1、View的事件分发 比如说你当前有一个非常简单的项目,只有一个Activity,并且Activity中只有一个按钮。你可能已经知道,如果想要给这个按钮注册一个点击事件,只需要调用: [java] view plaincopy button.setOnClickListener(new OnC

fengltxx的博客 1291

android触摸事件分发机制

一、      Android分发机制概述: Android如此受欢迎,就在于其优秀的交互性,这其中,Android优秀的事件分发机制功不可没。那么,作为一个优秀的程序员,要想做一个具有良好交互性的应用,必须透彻理解Android的事件分发机制。 要想充分理解android的分发机制,需要先对以下几个知识点有所了解: ①   View和ViewGroup什么? ②   事件 ③   Vi

Vegetable的博客 646

【知识梳理1】Android触摸事件机制

前言随着科学技术的发展,智能手机早已成为我们当代人身边必不可少的“伙伴”之一,堪比对象女友。每天我们对着手机重复的做着点击、滑动操作,而手机则随着我们的操作给我们展示她的精彩。

梦痕的专栏 2623

Android 触摸事件分发机制

如果该方法没有被覆写或调用了super的同名方法,则会调用 onInterceptTouchEvent 方法,如果该方法返回TRUE拦截事件,则交给自身的onTouchEvent 处理,如果该方法返回FALSE不拦截,则继续传给子子View(图中是View)的 dispatchTouchEvent方法处理。一般情况下,默认为FALSE。(1)如果经过子 View 层层传递或处理后,该事件被消费了(即返回了 TRUE),则 Activity 的分发方法也返回 TRUE,同样也表示该事件已经被消费了。

m0_61945436的博客 732

Android 触摸事件机制(三) View中触摸事件详解

本文将对View中触摸事件相关的内容进行介绍。重点介绍的是dispatchTouchEvent(), onTouchEvent()这两个API以及OnTouchListener接口。 注意:本文是基于Android 4.4.2版本进行介绍的! 目录 1. View中触摸事件的概述 2. View中触摸事件的源码解析 2.1. View中的dispatchTouchEvent 2

luojiayuan4523的专栏 2854
上一篇: 深入理解 Android Handler
下一篇: 音视频学习:使用NDK编译FFmpeg动态库
_蓝橙
博客等级 码龄7年 1179粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值