Android事件分发机制详解

本文详细解析Android事件分发机制,包括事件分发的对象、本质、传递路径、顺序及方法。通过源码分析,深入理解Activity、ViewGroup和View的事件处理流程,以及ACTION_DOWN、ACTION_MOVE和ACTION_UP等后续事件的层级传递。同时探讨onTouch()和onTouchEvent()的区别。
摘要由CSDN通过智能技术生成
一、前介
1、事件分发的对象是谁?

答:点击事件(Touch事件)

  • 定义
    当用户触摸屏幕时(View 或 ViewGroup派生的控件),将产生点击事件(Touch事件)

Touch事件的相关细节(发生触摸的位置、时间等)被封装成MotionEvent对象

  • 事件类型(4种)
    在这里插入图片描述
  • 特别说明:事件列
    从手指接触屏幕 至 手指离开屏幕,这个过程产生的一系列事件
    注:一般情况下,事件列都是以DOWN事件开始、UP事件结束,中间有无数的MOVE事件,action_cancel的具体动作是在非人为原因,比如父view打断了正在进行的子view,会执行action_cancel,如下图:
    在这里插入图片描述

即当一个点击事件(MotionEvent )产生后,系统需把这个事件传递给一个具体的 View 去处理。

2、事件分发的本质

答:将点击事件(MotionEvent)传递到某个具体的View & 处理的整个过程
即 事件传递的过程 = 分发过程。

3、事件在哪些对象之间进行传递?

答:Activity、ViewGroup、View

Android的UI界面由Activity、ViewGroup、View 及其派生类组成
UI界面
在这里插入图片描述
在这里插入图片描述

4、事件分发的顺序
  • 即 事件传递的顺序:Activity -> ViewGroup -> View

  • 即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到 View

在这里插入图片描述

5、事件分发过程由哪些方法协作完成?

答:dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()

其中Activity、ViewGroup、View分别对应的方法如下:

  • Activity:dispatchTouchEvent() 、onTouchEvent()
  • ViewGroup:dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()
  • View:dispatchTouchEvent() 、onTouchEvent()

示意图
下文会对这3个方法进行详细介绍

二、源码分析
  • 请谨记:Android事件分发流程 = Activity -> ViewGroup -> View
  • 即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到 View

要想充分理解Android分发机制,本质上是要理解:

  • Activity对点击事件的分发机制
  • ViewGroup对点击事件的分发机制
  • View对点击事件的分发机制

下面,我将通过源码,全面解析 事件分发机制

1、 Activity的事件分发机制

当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发

1.1 源码分析
/**
  * 源码分析:Activity.dispatchTouchEvent()
  */ 
    public boolean dispatchTouchEvent(MotionEvent ev) {
   

            // 一般事件列开始都是DOWN事件 = 按下事件,故此处基本是true
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
   

                onUserInteraction();
                // ->>分析1

            }

            // ->>分析2
            if (getWindow().superDispatchTouchEvent(ev)) {
   

                return true;
                // 若getWindow().superDispatchTouchEvent(ev)的返回true
                // 则Activity.dispatchTouchEvent()就返回true,则方法结束。即 :该点击事件停止往下传递 & 事件传递过程结束
                // 否则:继续往下调用Activity.onTouchEvent

            }
            // ->>分析4
            return onTouchEvent(ev);
        }


/**
  * 分析1:onUserInteraction()
  * 作用:实现屏保功能
  * 注:
  *    a. 该方法为空方法
  *    b. 当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法
  */
      public void onUserInteraction() {
    

      }
      // 回到最初的调用原处

/**
  * 分析2:getWindow().superDispatchTouchEvent(ev)
  * 说明:
  *     a. getWindow() = 获取Window类的对象
  *     b. Window类是抽象类,其唯一实现类 = PhoneWindow类;即此处的Window类对象 = PhoneWindow类对象
  *     c. Window类的superDispatchTouchEvent() = 1个抽象方法,由子类PhoneWindow类实现
  */
    @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
   

        return mDecor.superDispatchTouchEvent(event);
        // mDecor = 顶层View(DecorView)的实例对象
        // ->> 分析3
    }

/**
  * 分析3:mDecor.superDispatchTouchEvent(event)
  * 定义:属于顶层View(DecorView)
  * 说明:
  *     a. DecorView类是PhoneWindow类的一个内部类
  *     b. DecorView继承自FrameLayout,是所有界面的父类
  *     c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup
  */
    public boolean superDispatchTouchEvent(MotionEvent event) {
   

        return super.dispatchTouchEvent(event);
        // 调用父类的方法 = ViewGroup的dispatchTouchEvent()
        // 即 将事件传递到ViewGroup去处理,详细请看ViewGroup的事件分发机制

    }
    // 回到最初的调用原处

/**
  * 分析4:Activity.onTouchEvent()
  * 定义:属于顶层View(DecorView)
  * 说明:
  *     a. DecorView类是PhoneWindow类的一个内部类
  *     b. DecorView继承自FrameLayout,是所有界面的父类
  *     c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup
  */
  public boolean onTouchEvent(MotionEvent event) {
   

        // 当一个点击事件未被Activity下任何一个View接收 / 处理时
        // 应用场景:处理发生在Window边界外的触摸事件
        // ->> 分析5
        if (mWindow.shouldCloseOnTouch(this, event)) {
   
            finish()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值