美文网首页
Activity 对点击事件的分发机制

Activity 对点击事件的分发机制

作者: wuchao226 | 来源:发表于2020-08-17 19:38 被阅读0次

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

    事件分发流程概述

    注:Android事件分发流程 = Activity -> ViewGroup -> View
    :1 个点击事件发生后,事件先传到 Activity、再传到 ViewGroup、最终再传到 View

    1. Activity对点击事件的分发机制的源码分析

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

    /**
     * 源码分析:Activity.dispatchTouchEvent()
     */
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // 一般事件列开始都是DOWN事件 = 按下事件,故此处基本是true
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            // ->>分析1
            onUserInteraction();
        }
        // ->>分析2
        // 若getWindow().superDispatchTouchEvent(ev)的返回true
        // 则Activity.dispatchTouchEvent()就返回true,则方法结束。即 :该点击事件停止往下传递 & 事件传递过程结束
        // 否则:继续往下调用Activity.onTouchEvent
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
         // ->>分析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) {
        // mDecor = 顶层View(DecorView)的实例对象
        // ->> 分析3
        return mDecor.superDispatchTouchEvent(event);
    }
    
    /**
     * 分析3:mDecor.superDispatchTouchEvent(event)
     * 定义:属于顶层View(DecorView)
     * 说明:
     *     a. DecorView类是PhoneWindow类的一个内部类
     *     b. DecorView继承自FrameLayout,是所有界面的父类
     *     c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup
     */
    public boolean superDispatchTouchEvent(MotionEvent event) {
        // 调用父类的方法 = ViewGroup的dispatchTouchEvent()
        // 即 将事件传递到ViewGroup去处理,详细请看ViewGroup的事件分发机制
        return super.dispatchTouchEvent(event);
    }
     // 回到最初的调用原处
    
    /**
     * 分析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();
            return true;
        }
         // 即 只有在点击事件在Window边界外才会返回true,一般情况都返回false
        return false;
    }
    
    /**
     * 分析5:mWindow.shouldCloseOnTouch(this, event)
     */
    public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
        // 主要是对于处理边界外点击事件的判断:是否是DOWN事件,event的坐标是否在边界内等
        if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
                && isOutOfBounds(context, event) && peekDecorView() != null) {
            return true;
        }
        // 返回true:说明事件在边界外,即 消费事件
        // 返回false:未消费(默认)
        return false;
    }
    // 回到分析4调用原处
    

    2. 流程解析

    当一个点击事件发生时,从Activity的事件分发开始(Activity.dispatchTouchEvent()),流程解析如下:


    3. 方法总结

    核心方法主要是:dispatchTouchEvent()、onTouchEvent()

    3.1 dispatchTouchEvent()

    a. 调用时刻:用户触碰屏幕产生点击事件时
    b. 返回的结果有4种:


    3.2 onTouchEvent()

    a. 调用时刻:ViewGroup.dispatchTouchEvent() 返回 false 后,默认执行调用
    b. 返回的结果有2种:


    相关文章

      网友评论

          本文标题:Activity 对点击事件的分发机制

          本文链接:https://www.haomeiwen.com/subject/buvqjktx.html