返回顶部
首页 > 资讯 > 移动开发 >《Android》事件传递过程
  • 387
分享到

《Android》事件传递过程

事件Android 2022-06-06 13:06:26 387人浏览 独家记忆
摘要

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

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


--结束END--

本文标题: 《Android》事件传递过程

本文链接: https://lsjlt.com/news/29306.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 《Android》事件传递过程
    1、什么是事件传递? Android事件传递是指用户操作屏幕产生的一系列动作事件(按下、滑动、抬起)从外层传递到的内层的过程。 2、外层到内层如...
    99+
    2022-06-06
    事件 Android
  • Android事件传递机制
    实验环境 OS X 10.9 Eclipse(ADT) Android源码版本:API Level 19(Android 4.4) Android事件构成 在Android中...
    99+
    2022-06-06
    Android
  • Android触摸事件传递图解
    本博文讲解流程 TouchEvent相关事件简介 流程图分解讲解 总结与归纳 一.TouchEvent相关事件简介  android TouchEvent相关事件有...
    99+
    2022-06-06
    事件 Android
  • android事件传递与分发的流程是什么
    在Android中,事件传递与分发的流程如下:1. 事件产生:事件可以由用户触摸屏幕、按下按钮等方式产生。2. 事件分发:事件由系统...
    99+
    2023-10-18
    android
  • 深入解析Android中的事件传递
    前言 前段时间工作中遇到了一个问题,即在软键盘弹出后想监听back事件,但是在Activity中重写了对应的onKeyDown函数却怎么也监听不到,经过一阵Google之后才发...
    99+
    2022-06-06
    事件 Android
  • Android事件传递的方法有哪些
    Android中事件传递的方法有三种:1. 通过View的dispatchTouchEvent()方法进行事件传递。在这种方式下,事...
    99+
    2023-09-13
    android
  • Android触摸事件传递机制初识
    前言今天总结的一个知识点是Andorid中View事件传递机制,也是核心知识点,相信很多开发者在面对这个问题时候会觉得困惑,另外,View的另外一个难题滑动冲突,比如在ScrollView中嵌套ListView,都是上下滑动,这该如何解决呢...
    99+
    2023-05-31
    android 触摸 roi
  • 在Android中使用InputManagerService进行事件传递
    在Android中使用InputManagerService进行事件传递?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。InputManagerServicepublic voi...
    99+
    2023-05-31
    android 事件传递 inputmanagerservice
  • android点击事件传递机制是什么
    Android中的点击事件传递机制是基于View的层次结构进行的。当用户触摸屏幕时,Android系统会将触摸事件传递给最上层的Vi...
    99+
    2023-08-18
    android
  • 详细分析Android中onTouch事件传递机制
    onTach介绍 ontach是Android系统中整个事件机制的基础。Android中的其他事件,如onClick、onLongClick等都是以onTach为基础的。 on...
    99+
    2022-06-06
    Android
  • android点击事件传递机制怎么实现
    Android的点击事件传递机制是通过View的dispatchTouchEvent方法和onTouchEvent方法实现的。首先,...
    99+
    2023-10-20
    android
  • Vue click事件传递参数的示例教程
    目录简介只传自定义参数只传事件参数传事件和自定义参数动态参数(从局部取值)简介 说明         本文用示例介绍Vue中事件传参的方法。 ...
    99+
    2022-12-08
    Vue click事件传递参数 Vue click事件 vue传递参数
  • 老生常谈android中的事件传递和处理机制
    一直以来,都被android中的事件传递和处理机制深深的困扰!今天特意来好好的探讨一下。现在的感觉是,只要你理解到位,其实事件的 传递和处理机制并没有想象中的那么难。总之,不要...
    99+
    2022-06-06
    事件 Android
  • Android Drawerlayout侧拉栏事件传递问题的解决方法
    先来看看错误分析: "在侧拉栏打开的时候出现了点击之后侧拉栏下面的页面也接收到了点击事件。" 解决方案: rootDrawerlayout.setDrawerListene...
    99+
    2022-06-06
    方法 事件 drawerlayout Android
  • 微信小程序点击事件(bindtap)传递参数
    小程序在组件上绑定事件后,传递参数的方式不同于前端开发其他场景中直接加参数的方式,小程序在参数的传递时,采用事件对象的自定义属性的方式,具体实现如下: wxml: ...
    99+
    2023-09-20
    微信小程序 小程序
  • vue组件间怎么实现事件传递
    vue组件间怎么实现事件传递,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一...
    99+
    2024-04-02
  • Android Touch事件分发过程详解
    本文以实例形式讲述了Android Touch事件分发过程,对于深入理解与掌握Android程序设计有很大的帮助作用。具体分析如下: 首先,从一个简单示例入手: 先看一个示例如...
    99+
    2022-06-06
    touch Android
  • android数据传递
    将MainActivity页面的数据:姓名、年龄、性别,传递给新的Activity页面显示出来 MainActivity.java页面 pack...
    99+
    2022-06-06
    Android
  • vue如何实现属性事件传递
    这篇文章给大家分享的是有关vue如何实现属性事件传递的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。属性事件传递写过高阶组件的童鞋可能都会碰到过将加工过的属性向下传递的情况,如果碰...
    99+
    2024-04-02
  • vue子组件中怎么通过自定义事件向父组件传递数据
    这篇文章将为大家详细讲解有关vue子组件中怎么通过自定义事件向父组件传递数据,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。使用v-on绑定自定义事件可以让子...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作