Android事件分发机制

作者: NoBugException | 来源:发表于2019-07-13 23:21 被阅读9次

    Android事件分发机制算是Android高级篇的基础了,程序猿一定要对其有所了解。

    (1)确定事件分发的对象

    当用户点击View或ViewGroup时就产生了触摸(Touch)事件,Touch相关的细节被封装成了MotionEvent对象。当我们自定义View时经常重写onTouchEvent方法,比如:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_UP:
                break;
    
        }
        return super.onTouchEvent(event);
    }
    

    onTouchEvent可以监听到触摸(Touch)事件。

    常用的Touch事件有四种:

    • MotionEvent.ACTION_DOWN:按下View
    • MotionEvent.ACTION_MOVE:滑动View
    • MotionEvent.ACTION_CANCEL:非人为原因取消事件
    • MotionEvent.ACTION_UP:抬起View

    View事件的基本流程是:

    用户按下View,触发ACTION_DOWN事件-->用户拖动或滚动View,触发ACTION_MOVE事件-->用户抬起,放开View,触发ACTION_UP事件。
    ACTION_CANCEL事件的触发非人为触发,也许是程序猿代码中主动取消,也许是发生了异常导致取消。

    (2)事件分发的本质

    本质上是将点击时间的出来传递到View本身去处理,这个过程叫做分发过程。

    (3)事件传递的载体

    事件传递的载体是:Activity(Window)、ViewGroup、View。

    假设点击一个按钮,事件的传递顺序是:Activity(Window)-->ViewGroup-->View

    下图是Activity、ViewGroup、View的层级图,其实Activity上面还有一层叫PhoneWindow,但不是本章重点。

    图片.png

    请先记住触摸事件的传递顺序:Activity(Window)-->ViewGroup-->View

    • Activity:它是Android界面的基本
    • ViewGroup:有线性布局、相对布局、约束布局、帧布局、表格布局、RecyclerView、其它自定义ViewGroup
    • View:比如,TextView、ImageView或者其它自定义View
    (4)事件的分发由哪些方法协调?

    事件的分发由dispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()相互协调的。

    • onTouchEvent():负责处理触摸事件

    事件分发到最后,总是由 onTouchEvent()来处理触摸事件。

    它的返回值代表的意义:
    [true]:直接结束
    [super或false]:执行上级的onTouchEvent()方法

    • dispatchTouchEvent() :负责分发触摸事件

    事件的分发总是由这个方法开始,根据不同的返回值做出相应的处理:
    [true]:直接结束事件的分发
    [false]:执行上级的onTouchEvent()方法去处理触摸事件,最后结束事件的分发
    [super]:继续分发事件

    • onInterceptTouchEvent():负责拦截触摸事件

    只有在ViewGroup中才有这个方法,这个方法专门负责事件的拦截工作,根据返回值处理不同的结果:
    [true]:执行ViewGroup的onTouchEvent()事件;
    [super或false]:执行View的dispatchTouchEvent()方法

    (5)事件在Activity中是如何处理的?

    前提条件:Activity中有一个按钮(View),按钮在一个布局(ViewGroup)中。

    我们都知道触摸事件的传递顺序:Activity(Window)-->ViewGroup-->View,那么在Activity中事件是如何处理的呢?

    Activity中有一个dispatchTouchEvent方法,当有触摸事件时,最先执行的方法就是dispatchTouchEvent,它的返回类型是一个boolean类型,默认情况下返回super.dispatchTouchEvent(ev),当返回super.dispatchTouchEvent(ev)时,事件将传递给ViewGroup,但是如果返回true或者false时,事件就会直接结束,不会传递给ViewGrou,更不会传递给View。

    比如,在Activity中重写dispatchTouchEvent

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return true;
    }
    

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return false;
    }
    

    这种情况下,按钮是不可能监听到点击事件的,一般我们不会在Activity中重写dispatchTouchEvent方法,就默认返回super.dispatchTouchEvent(ev),让它把事件传递到ViewGroup即可。

    (6)事件在ViewGroup中是如何处理的?

    当事件从Activity传递到ViewGroup之后,ViewGroup是如何处理这个事件的呢?

    在ViewGroup中,事件首先被分发到ViewGroup的dispatchTouchEvent方法:

    • 如果返回true则直接结束分发;
    • 如果返回false,则执行Activity的onTouchEvent方法,Activity的onTouchEvent方法不管返回什么都直接结束分发;
    • 如果返回super.dispatchTouchEvent(ev),则执行onInterceptTouchEvent方法;

    onInterceptTouchEvent的返回值解析如下:

    • 如果返回true,则执行ViewGroup的onTouchEvent方法;
    • 如果返回super或者false,则执行View的dispatchTouchEvent方法;

    onTouchEvent的返回值解析如下:

    • 返回true,直接结束事件
    • 否则,执行Activity的onTouchEvent方法
    (7)事件在View中是如何处理的?

    在View中,事件首先被分发到View的dispatchTouchEvent方法:

    • 返回true,结束事件
    • 返回false,执行ViewGroup的onTouchEvent方法
    • 返回super,则直接执行View的onTouchEvent方法
    (8)事件分发流程图(是重点,要记住)

    以上这张图要记住,上面说了那么多废话,记不住不要紧,只要将这张图记住就可以了。

    事件分发流程图.png
    (9)总结
    • 请记住以上的一张图,因为这张图才是世间分发机制的精髓所在,其实这张图就是事件分发机制的全部了;
    • 事件分发机制是实现自定义View的基础,所以一定要了解;
    • 现在很多嵌套View都存在触摸事件冲突问题,这时就需要事件分发机制的知识来解决这个问题了。

    [本章完...]

    相关文章

      网友评论

        本文标题:Android事件分发机制

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