Android事件分发机制的探索与发现之ViewGroup篇

版权声明:本文来自门心叼龙的博客,属于原创内容,转载请注明出处:https://blog.csdn.net/geduo_83/article/details/90145083

github源码下载地址:https://github.com/geduo83/android-touch-event
Android事件分发机制的探索与发现之View篇
Android事件分发机制的探索与发现之ViewGroup篇
Android事件分发机制的探索与发现之Activity篇
Android事件分发机制的探索与发现之总结篇
Android事件分发机制在实战开发中的应用之一
Android事件分发机制在实战开发中的应用之二

上一篇文章我们主要讲View MyButton的事件分发流程,这篇主要来分析MyLayout的事件分发流程,研究方法一样,通过改变返回值,来观察事件的分发流程

MyLayout的onInterceptTouchEvent方法

MyLayout其本质是一个ViewGroup,ViewGroup比View就多了一个事件拦截的方法onInterceptTouchEvent,因此我们MyLayout对的测试先从它的拦截方法开始

  • 情况1:调用父类的同名方法
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return super.onInterceptTouchEvent(ev);
    }

其实我们上面已经测试过了,我们的测试MyButton的相关方法的时候,MyLayout的onInterceptTouchEvent方法调用的就是父类的同名方法,

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyButton dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN

事件到达MyLayout onInterceptTouchEvent的方法后,调用了父类的同名方法super.onInterceptTouchEvent后,事件会继续传递给MyButton的dispatchTouchEvent 方法进行事件分发

  • 情况2:返回false
public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return false;
    }

点击测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyButton dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyButton onTouchEvent start:ACTION_DOWN
----------------------------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_UP
V/MYTAG: MyButton dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyButton onTouchEvent start:ACTION_UP

我们发现MyLayout的onInterceptTouchEvent方法返回false和调用父类的同名方法super.onInterceptTouchEvent方法,事件的传递流程都是一样的

  • 情况3:返回ture
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }
@Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.v(TAG,"MyLayout onTouchEvent start:"+MotionEventUtil.getMotionEventName(event));
        return super.onTouchEvent(event);
    }

点击测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity onTouchEvent start:ACTION_DOWN
--------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MainActivity onTouchEvent start:ACTION_UP

如果返回true触摸事件不会继续传递给MyButton了,而直接就被MyLayout拦截掉了,并将事件传递给自己的onTouchEvent方法进行消费

好了,关于MyLayout的onInterceptTouchEvent方法我们彻底测试完毕了,我们不难得出结论:当onInterceptTouchEvent返回false和调用父类的同名方法的时候,触摸事件会继续往下传递,当返回true的时候该事件就被被拦截掉,并交给自己的onTouchEvent方法进行处理

MyLayout的onTouchEvent方法

  • 情况1:调用父类的同名方法
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.v(TAG,"MyLayout onTouchEvent start:"+MotionEventUtil.getMotionEventName(event));
        return super.onTouchEvent(event);
    }

注意了,为了便于测试我们让onInterceptTouchEvent返回true
测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity onTouchEvent start:ACTION_DOWN
--------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MainActivity onTouchEvent start:ACTION_UP

通过测试日志我们可以发现,当MyLayout的onTouchEvent调用父类的同名方法,触摸事件会继续回传给MainActivity的onTouchEvent进行处理,其实在前面我们测试过了,当MyButton的onTouchEvent方法返回false和dispathTouchEvent方法返回false触摸事件都会回传给MyLayout的onTouchEvent方法,紧接着就继续回传给MainActivity的onTouchEvent方法

  • 情况2:返回false
 @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.v(TAG,"MyLayout onTouchEvent start:"+MotionEventUtil.getMotionEventName(event));
        return false;
    }

测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity onTouchEvent start:ACTION_DOWN
---------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_MOVE
V/MYTAG: MainActivity onTouchEvent start:ACTION_MOVE
---------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MainActivity onTouchEvent start:ACTION_UP

返回false和调用父类的同名方法,事件传递的流程都是一样的,触摸事件都回传给了MainActivity的onTouchEvent方法进行处理

  • 情况3:返回true
@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout onInterceptTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.v(TAG,"MyLayout onTouchEvent start:"+MotionEventUtil.getMotionEventName(event));
        return true;
    }

测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN
----------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout onTouchEvent start:ACTION_UP

返回true很简单,事件被自己消费掉了
好了,截止到线程关于MyLayout的onTouchEvent方法就分析完毕了,我们不难得出结论:MyLayout的onTouchEvent方法返回true事件就消费掉了,如果返回false和调用父类的同名方法super.onTouchEvent方法事件就会继续回传给MainActivity的onTouchEvent方法进行处理

MyLayout的dispatchTouchEvent方法

  • 情况1:调用父类的同名方法
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return super.dispatchTouchEvent(ev);
    }

上面也都测试过了,如果MyLayout的dispatchTouchEvent调用了父类的同名方法则触摸事件会继续传递给它自己的onInterceptTouchEvent方法进行处理,测试日志如下:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onInterceptTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout onTouchEvent start:ACTION_DOWN
  • 情况2:返回false
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return false;
}

点击测试:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MainActivity onTouchEvent start:ACTION_DOWN
--------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MainActivity onTouchEvent start:ACTION_UP

返回false触摸事件直接就回传了给了MainActivity的onTouchEvent方法进行处理了

  • 情况3:返回true
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.v(TAG,"MyLayout dispatchTouchEvent start:"+MotionEventUtil.getMotionEventName(ev));
        return true;
    }

点击测试结果:

V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_DOWN
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_DOWN
----------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_MOVE
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_MOVE
----------------------------------------------------------
V/MYTAG: MainActivity dispatchTouchEvent start:ACTION_UP
V/MYTAG: MyLayout dispatchTouchEvent start:ACTION_UP

返回true,触摸事件就直接被自己的dispatchTouchEvent方法消费掉了
好了,截止目前关于MyLayout的dispathTouchEvent方法就彻底分析完毕了,结论如下:MyLayout的dispatchTouchEvent方法调用父类的同名方法则事件会继续往下传递给自己的onInterceptTouchEvent方法,如果返回false则事件会回传给MainActivity的onTouchEvent方法进行处理,如果返回为true则就自行消费掉了

你可能感兴趣的:(Android事件分发机制的探索与发现之ViewGroup篇)