美文网首页Android自定义ViewView事件分发Android基础知识
Android事件分发机制的探索与发现之ViewGroup篇

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

作者: 门心叼龙 | 来源:发表于2019-05-12 18:36 被阅读2次

    版权声明:本文来自门心叼龙的博客,属于原创内容,转载请注明出处: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篇

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