我的编程空间,编程开发者的网络收藏夹
学习永远不晚

《Android》事件传递过程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

《Android》事件传递过程

1、什么是事件传递?
Android事件传递是指用户操作屏幕产生的一系列动作事件(按下、滑动、抬起)从外层传递到的内层的过程。

2、外层到内层如何理解?
Activity —> Window ----> ViewGroup ---->View

3、必须了解的基础
3.1 首先要知道传递的对象是一个MotionEvent类的对象。这个类中定义了动作常量,比如“按下” public static final int ACTION_DOWN = 0等等。
3.2 第二要知道3个重要的方法 :
boolean dispatchTouchEvent(MotionEvent ev) 分发事件ev
boolean onInterceptTouchEvent(MotionEvent ev) 是否拦截事件ev
boolean onTouchEvent(MotionEvent ev) 是否消耗事件ev
3.3经常给view设置的有关事件监听的方法
view.setOnTouchListener(…) 触摸事件监听
view.setOnClickListener(…) 单击事件监听

4、事件传递的具体过程
4.1产生事件:
手指触碰屏幕首先产生一个MotionEvent Down事件,随着手指滑动产生多个MotionEvent Move事件,最后抬起手指产生一个MotionEvent Up事件
4.2 事件在Activity中:
Activity中有dispatchTouchEvent()、onTouchEvent()2个方法。

 
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }
     
    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }
        return false;
    }

dispatchTouchEvent中事件先去传给getWindow().superDispatchTouchEvent(ev)去做判断,如果返回为true,则直接结束。如果为false 触发Activity的onTouchEvent()方法。
也就是说在Activity中通过getWindow().superDispatchTouchEvent(ev)方法将事件传递给了Window。
4.3 事件在Window中:
getWindow().superDispatchTouchEvent(ev)调用Window内部的superDispatchTouchEvent()方法。

 
    public abstract boolean superDispatchTouchEvent(MotionEvent event);

这是一个抽象方法。具体逻辑在Window的唯一继承类PhoneWidow中:

 @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

事件在window中没有做任务处理,直接通过mDecor.superDispatchTouchEvent(event)传递给了DecorView。DecorView是view的最顶层,被定义在PhoneWindow中的一个对象。它是一个继承自FrameLayout的ViewGroup。

// This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;

4.4 事件在ViewGroup中:
事件传递到DecorView的superDispatchTouchEvent()方法

public boolean superDispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }

调用了super.dispatchTouchEvent(event),这个super其实就是ViewGroup。
在ViewGroup中有dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()3个方法。
由于源码过长,其中还包含很多控制单元,为了分析过程直接贴出来不直观,不想篇幅过长,自己去查看印象更深刻!直接总结:
(1)事件MotionEvent传递给dispatchTouchEvent(ev)进行事件分发
(2)在分发方法内部调用了onInterceptTouchEvent(ev)判读是否对事件拦截(返回false代表不拦截,true表示拦截。默认为false)。
(3) onInterceptTouchEvent(ev)返回true, 说明要拦截事件,ev会交给此viewGroup处理。
(4)如果viewGroup设置了OnTouchListener,onTouch()会被调用,onTouch()返回false viewGroup的onTouchEvent会被调用。onTouch()返回true viewGroup的onTouchEvent会被屏蔽掉。
(5)onInterceptTouchEvent(ev)返回false,不拦截事件,将会把事件传递给 子View(view或viewGroup)的dispatchTouchEvent(ev)处理。如果子view是ViewGroup则继续从(1)开始循环。

4.4 事件在View中:
在View中有dispatchTouchEvent()、onTouchEvent()2个方法。没有onInterceptTouchEvent()
与ViewGroup过程相似,毕竟ViewGroup继承自View。ViewGroup也没有重写onTouchEvent,所以ViewGroup中onTouchEvent()方法就是View中的方法。
(1)事件MotionEvent传递给dispatchTouchEvent(ev)进行事件分发
(2)如果view设置了OnTouchListener,onTouch()会被调用,onTouch()返回false view的onTouchEvent会被调用。onTouch()返回true view的onTouchEvent会被屏蔽掉。

5、setOnTouchListener()\setOnClickListener()\onTouchEvent()调用关系:
下面是view的dispatchTouchEvent()源码


    public boolean dispatchTouchEvent(MotionEvent event) {
        // If the event should be handled by accessibility focus first.
        if (event.isTargetAccessibilityFocus()) {
            // We don't have focus or no virtual descendant has it, do not handle the event.
            if (!isAccessibilityFocusedViewOrHost()) {
                return false;
            }
            // We have focus and got the event, then use normal event dispatch.
            event.setTargetAccessibilityFocus(false);
        }
        boolean result = false;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }
        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // Defensive cleanup for new gesture
            stopNestedScroll();
        }
        if (onFilterTouchEventForSecurity(event)) {
            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
                result = true;
            }
            //noinspection SimplifiableIfStatement
            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;
            }
        }
        if (!result && mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        // Clean up after nested scrolls if this is the end of a gesture;
        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
        // of the gesture.
        if (actionMasked == MotionEvent.ACTION_UP ||
                actionMasked == MotionEvent.ACTION_CANCEL ||
                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
            stopNestedScroll();
        }
        return result;
    }

其中判断了mOnTouchListener != null && mOnTouchListener.onTouch(this, event)条件,之后根据返回结果判断是否去调用onTouchEvent(event)。验证了OnTouchListener 调用优先,并控制onTouchEvent()的调用。
在view的onTouchEvent()方法中

 public boolean onTouchEvent(MotionEvent event) {
        ...代码省略...
        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    ...代码省略...
                            if (!focusTaken) {
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    performClickInternal();
                                }
                            }
                            ...代码省略...
                        }
         ...代码省略...

performClickInternal()方法会调performClick(),贴出performClick()源码

public boolean performClick() {
        // We still need to call this method to handle the cases where performClick() was called
        // externally, instead of through performClickInternal()
        notifyAutofillManagerOnClick();
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        notifyEnterOrExitForAutoFillIfNeeded(true);
        return result;
    }

这里触发了li.mOnClickListener.onClick(this)。说明点击事件onClick是在onTouchEvent中间接调用的。

6、事件交由上层处理
子视图不能处理事件时候,onTouchEvent 返回false,事件将交给父视图的onTouchEvent调用。如果还不能处理事件则依次往上传递。直到Activity。也就是在getWindow().superDispatchTouchEvent(ev)返回了false。将调用Activity的onTouchEvent()方法。


作者:calmerman


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

《Android》事件传递过程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

《Android》事件传递过程

1、什么是事件传递? Android事件传递是指用户操作屏幕产生的一系列动作事件(按下、滑动、抬起)从外层传递到的内层的过程。 2、外层到内层如何理解? Activity —> Window ----> ViewGroup ---->Vie
2022-06-06

Android事件传递机制

实验环境 OS X 10.9 Eclipse(ADT) Android源码版本:API Level 19(Android 4.4)Android事件构成 在Android中,事件主要包括点按、长按、拖拽、滑动等,点按又包括单击和双击,另外还
2022-06-06

Android触摸事件传递图解

本博文讲解流程 TouchEvent相关事件简介 流程图分解讲解 总结与归纳一.TouchEvent相关事件简介 android TouchEvent相关事件有 1 dispatchTouchEvent 这个方法用来分发TouchEve
2022-06-06

android事件传递与分发的流程是什么

在Android中,事件传递与分发的流程如下:1. 事件产生:事件可以由用户触摸屏幕、按下按钮等方式产生。2. 事件分发:事件由系统通过ViewGroup的dispatchTouchEvent()方法开始分发。dispatchTouchEv
2023-10-18

Android事件传递的方法有哪些

Android中事件传递的方法有三种:1. 通过View的dispatchTouchEvent()方法进行事件传递。在这种方式下,事件首先由Activity的dispatchTouchEvent()方法调用,然后传递给根布局的dispatc
2023-09-13

Android触摸事件传递机制初识

前言今天总结的一个知识点是Andorid中View事件传递机制,也是核心知识点,相信很多开发者在面对这个问题时候会觉得困惑,另外,View的另外一个难题滑动冲突,比如在ScrollView中嵌套ListView,都是上下滑动,这该如何解决呢
2023-05-31

深入解析Android中的事件传递

前言 前段时间工作中遇到了一个问题,即在软键盘弹出后想监听back事件,但是在Activity中重写了对应的onKeyDown函数却怎么也监听不到,经过一阵Google之后才发现需要重写View的dispatchKeyEventPreIme
2022-06-06

android点击事件传递机制是什么

Android中的点击事件传递机制是基于View的层次结构进行的。当用户触摸屏幕时,Android系统会将触摸事件传递给最上层的View,然后逐级向下传递,直到找到具体响应该事件的View。点击事件传递机制主要包括以下几个步骤:1. 触摸事
2023-08-18

在Android中使用InputManagerService进行事件传递

在Android中使用InputManagerService进行事件传递?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。InputManagerServicepublic voi
2023-05-31

详细分析Android中onTouch事件传递机制

onTach介绍 ontach是Android系统中整个事件机制的基础。Android中的其他事件,如onClick、onLongClick等都是以onTach为基础的。 onTach包括从手指按下到离开手机屏幕的整个过程,在微观形式上,具
2022-06-06

android点击事件传递机制怎么实现

Android的点击事件传递机制是通过View的dispatchTouchEvent方法和onTouchEvent方法实现的。首先,当用户触摸屏幕时,事件会被传递给Activity的dispatchTouchEvent方法。dispatch
2023-10-20

Vue click事件传递参数的示例教程

这篇文章主要介绍了Vue click事件传递参数--方法/教程/实例,本文用示例介绍Vue中事件传参的方法,采用click这个事件进行展示,结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
2022-12-08

Android Drawerlayout侧拉栏事件传递问题的解决方法

先来看看错误分析: "在侧拉栏打开的时候出现了点击之后侧拉栏下面的页面也接收到了点击事件。"解决方案:rootDrawerlayout.setDrawerListener(new DrawerLayout.DrawerListener()
2022-06-06

老生常谈android中的事件传递和处理机制

一直以来,都被android中的事件传递和处理机制深深的困扰!今天特意来好好的探讨一下。现在的感觉是,只要你理解到位,其实事件的 传递和处理机制并没有想象中的那么难。总之,不要自己打击自己,要相信自己能掌握这块知识。好了,下面是我今天的收获
2022-06-06

Android Touch事件分发过程详解

本文以实例形式讲述了Android Touch事件分发过程,对于深入理解与掌握Android程序设计有很大的帮助作用。具体分析如下: 首先,从一个简单示例入手: 先看一个示例如下图所示:布局文件 :
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录