Android 事件分发MotionEvent.ACTION_DOWN 按下事件分发流程( Activity | ViewGroup | View )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 事件分发MotionEvent.ACTION_DOWN 按下事件分发流程( Activity | ViewGroup | View )相关的知识,希望对你有一定的参考价值。

android 事件分发 系列文章目录


【Android 事件分发】事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 )
【Android 事件分发】事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 一 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 二 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 三 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 四 | View 事件传递机制 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 五 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 六 )
【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 七 )

【Android 事件分发】ItemTouchHelper 简介 ( 拖动/滑动事件 | ItemTouchHelper.Callback 回调 )
【Android 事件分发】ItemTouchHelper 实现侧滑删除 ( 设置滑动方向 | 启用滑动操作 | 滑动距离判定 | 滑动速度判定 | 设置动画时间 | 设置侧滑触发操作 )
【Android 事件分发】ItemTouchHelper 实现拖动排序 ( 设置滑动方向 | 启启用长按拖动功能 | 拖动距离判定 | 设置拖动触发操作 )

【Android 事件分发】ItemTouchHelper 事件分发源码分析 ( 绑定 RecyclerView )
【Android 事件分发】ItemTouchHelper 源码分析 ( OnItemTouchListener 事件监听器源码分析 )
【Android 事件分发】ItemTouchHelper 源码分析 ( OnItemTouchListener 事件监听器源码分析 二 )

【Android 事件分发】MotionEvent.ACTION_DOWN 按下事件分发流程( Activity | ViewGroup | View )






一、事件分发相关类和方法



Android 事件分发涉及到的类有 3 3 3 个 , Activity , ViewGroup , View ;

Android 事件分发涉及到的如下 7 7 7 个方法 :

  • Activity 类涉及到 dispatchTouchEvent , onTouchEvent , 2 2 2 个方法 ;
public class MainActivity extends AppCompatActivity {
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
}
  • ViewGroup 涉及到 dispatchTouchEvent , onInterceptTouchEvent , onTouchEvent , 3 3 3 个方法 ;
public class MyConstraintLayout extends ConstraintLayout {
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
}
  • View 涉及到 dispatchTouchEvent , onTouchEvent , 2 2 2 个方法 ;
public class MyButton extends androidx.appcompat.widget.AppCompatButton {
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
}




二、Activity 的事件传递




1、Activity.dispatchTouchEvent 方法事件传递机制


事件来源 :

① 驱动层产生触摸事件, 由 WindowManagerService 传递到 Activity


事件分发 :

① 停止传递 : 如果返回 true / false , 说明事件被消费 , 停止传递

② 继续传递 : 如果返回 super.dispatchTouchEvent(ev) , 那么继续向下传递, 按照如下顺序逐层传递 : Activity -> PhoneWindow -> DecorView -> ViewGrope , 最终传递到 ViewGroup, 调用 ViewGroup 的 dispatchTouchEvent 方法

    /**
     * 该方法是页面事件分发入口
     *
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      驱动层产生触摸事件, 由 WindowManagerService 传递到 Activity
     *  事件分发 :
     *      如果返回 true / false, 说明事件被消费, 停止传递
     *      如果返回 super.dispatchTouchEvent(ev), 那么继续向下传递, 按照如下顺序逐层传递 :
     *          Activity -> PhoneWindow -> DecorView -> ViewGrope
     *          最终传递到 ViewGroup, 调用 ViewGroup 的 dispatchTouchEvent 方法
     *
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

2、Activity.onTouchEvent 方法事件传递机制


事件来源 :

① 布局容器 ViewGroup 的 dispatchTouchEvent 方法返回 false ;

② 布局容器 ViewGroup 的 onTouchEvent 方法返回 false / super.onTouchEvent(event) ;


事件分发 : 这是事件传递的终点, 返回值无所谓

① 返回 true 说明事件被消费了 ;

    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      布局容器 ViewGroup 的 dispatchTouchEvent 方法返回 false
     *      布局容器 ViewGroup 的 onTouchEvent 方法返回 false / super.onTouchEvent(event)
     *   事件分发 : 这是事件传递的终点, 返回值无所谓
     *      返回 true 说明事件被消费了
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }




三、ViewGroup 的事件传递




1、ViewGroup.dispatchTouchEvent 方法事件传递机制


    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      从 Activity 的 dispatchTouchEvent 传递而来
     *      从父容器 ViewGroup 的 dispatchTouchEvent 传递而来
     *  事件分发 :
     *      如果返回 true, 表示事件被消费, 停止传递
     *      如果返回 false, 则传递给父控件的 onTouchEvent 方法
     *      如果返回 super.dispatchTouchEvent(ev) , 则继续向下传递到 onInterceptTouchEvent 方法
     *
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

2、ViewGroup.onInterceptTouchEvent 方法事件传递机制


    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      从 本类 的 dispatchTouchEvent 方法传递而来
     *  事件分发 :
     *      返回 true, 则停止向后传递, 执行本类的 onTouchEvent 方法
     *          如果需要拦截, 返回true
     *      返回 false / super.onInterceptTouchEvent(ev),
     *          则继续向 子容器/子组件 的 dispatchTouchEvent 方法传递; ( 这里是子组件 )
     *          默认不拦截
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev);
    }

3、ViewGroup.onTouchEvent 方法事件传递机制


    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      本类的 onInterceptTouchEvent 方法返回 true
     *      子组件/子容器 的 dispatchTouchEvent 方法返回 false
     *      子组件/子容器 的 onTouchEvent 方法返回 false / super.onTouchEvent(event)
     *   事件分发 :
     *      返回 true 说明事件被消费了, 不再向下传递
     *      返回 false / super.onTouchEvent(event) , 则需要继续向下传递
     *          向父容器的 onTouchEvent 传递
     *
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }




四、View 的事件传递




1、View .dispatchTouchEvent 方法事件传递机制


    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      父容器 ViewGroup 的 onInterceptTouchEvent 如果返回 false / super.onInterceptTouchEvent(ev)
     *          将事件传递到该方法
     *  事件分发 :
     *      如果返回 true, 表示事件被消费, 停止传递
     *      如果返回 false, 则传递给父控件的 onTouchEvent 方法
     *      如果返回 super.dispatchTouchEvent(ev) , 则向本类的 onTouchEvent 方法传递
     *
     * @param event
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }

2、View .onTouchEvent 方法事件传递机制


    /**
     * 针对 ACTION_DOWN 事件分析 :
     *  事件来源 :
     *      本类的 dispatchTouchEvent 方法返回 super.dispatchTouchEvent(event)
     *   事件分发 :
     *      返回 true 说明事件被消费了, 不再向下传递
     *      返回 false / super.onTouchEvent(event) , 则需要继续向下传递
     *          向父容器的 onTouchEvent 传递
     *
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }




五、事件分发示意图



网上找了两张示意图 , 参考上述源码注释理解 ;





总结



通过控制上述 7 7 7 个方法的 3 3 3 种返回值 true / false / super , 控制整体 Activity 界面组件的事件分发 ;


事件分发规律 :

① 事件消费 : dispatchTouchEvent 或 onTouchEvent , 一旦返回 true , 则标明事件消费 , 不再继续分发事件 ; 注意 : Activity 的 dispatchTouchEvent 除外 , 其返回 true / false 都表示事件已消费 , 只有 super 时才向下传递 ;

② 向父容器传递 : dispatchTouchEvent 或 onTouchEvent , 一旦返回 false , 一律将事件传递给父容器的 onTouchEvent 方法 ;

③ 事件拦截 : onInterceptTouchEvent 返回 true , 则执行自己的 , 返回 false 则传递到子组件的 dispatchTouchEvent 方法 ;

以上是关于Android 事件分发MotionEvent.ACTION_DOWN 按下事件分发流程( Activity | ViewGroup | View )的主要内容,如果未能解决你的问题,请参考以下文章

Android 事件分发事件分发源码分析 ( ViewGroup 事件传递机制 三 )

Android 事件分发事件分发源码分析 ( ViewGroup 事件传递机制 二 )

Android 事件分发事件分发源码分析 ( ViewGroup 事件传递机制 一 )

Android 事件分发事件分发源码分析 ( ViewGroup 事件传递机制 七 )

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

Android 事件分发ItemTouchHelper 事件分发源码分析 ( 绑定 RecyclerView )