super.dispatchTouchEvent(event)使用

结论

dispatchTouchEvent、onTouchEvent中
ACTION_DOWN:返回true,说明当前View来处理事件,后续事件也要处理,事件不再向下传递;返回false,说明当前View不处理事件,后续事件直接由上一级View处理,当前View也不会再接收到后续事件
ACTION_MOVE、ACTION_UP:返回true,说明其子View已经接收了DOWN事件,这里返回true只会导致该部分事件不再继续向下传递(但也不会传递当前View的onTouchEvent处理),对于没有返回true的事件还按正常流程传递

onInterceptTouchEvent中
无论在什么时候拦截,接下来的事件都将传递给当前View的onTouchEvent来处理

注意
super.dispatchTouchEvent(event)的返回值取决于子View或当前View的onTouchEvent对应事件的返回值

测试代码

布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <com.cn.test.TextLinerLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.cn.test.TestButton
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="#f0f"/>

    </com.cn.test.TextLinerLayout>

</LinearLayout>
TextLinerLayout中部分代码
public class TextLinerLayout extends LinearLayout {
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---");

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            	//dispatchTouchEvent 返回值在一定情况下取决于onTouchEvent的返回值
                boolean b = super.dispatchTouchEvent(event);//这里只是调用下
                Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---down=="+b);
                return true;
            case MotionEvent.ACTION_MOVE:
                boolean b1 = super.dispatchTouchEvent(event);//这里只是调用下
                Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move=="+b1);
                return true;
            case MotionEvent.ACTION_UP:
                Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---up");
                break;
        }
        return super.dispatchTouchEvent(event);

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---");
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("liuyzz:TextLinerLayout:", "onTouchEvent---");
        return super.onTouchEvent(event);
    }
}
TestButton部分代码
public class TestButton extends android.support.v7.widget.AppCompatButton {

	@Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("liuyzz:button:", "dispatchTouchEvent---");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                boolean b = super.onTouchEvent(event);//默认返回false
                Log.d("liuyzz:button:", "onTouchEvent---down=="+b);
                return true;   //这里的返回值直接影响父View的super.dispatchTouchEvent(event)的返回值
            case MotionEvent.ACTION_MOVE:
                boolean b1 = super.onTouchEvent(event);//这里只是调用下
                Log.d("liuyzz:button:", "onTouchEvent---move=="+b1);
                return true;   //这里的返回值直接影响父View的super.dispatchTouchEvent(event)的返回值
            case MotionEvent.ACTION_UP:
                Log.d("liuyzz:button:", "onTouchEvent---up");
                break;
        }
        return super.onTouchEvent(event);  //这里的返回值直接影响父View的super.dispatchTouchEvent(event)的返回值
    }
}
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false//默认返回false
//这里的真假,取决于子View中down中返回的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==true 

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---move==false
//这里的真假,取决于子View中move中返回的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move==true 
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---up

由打印结果得知:TextLinerLayout的dispatchTouchEvent中调用super.dispatchTouchEvent方法,会执行onInterceptTouchEvent–>子View的dispatchTouchEvent–>子View的onTouchEvent,而返回值取决于自己或者子View的onTouchEvent的返回值

当把TextLinerLayout的dispatchTouchEvent的ACTION_DOWN事件返回false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==true

由打印结果得知(只打印以上日志,继续滑动也不会打印):ACTION_DOWN事件返回false则后续事件不会再分发给TextLinerLayout所以只会打印以上这些日志

当把TestButton中onTouchEvent方法中ACTION_DOWN事件返回false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false
//因子View的down事件不处理,所以会调用父View的onTouchEvent
D/liuyzz:TextLinerLayout:: onTouchEvent---
//因为子View中onTouchEvent的DOWN中返回false,所以大部分情况下第8行的值取决于onTouchEvent的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==false 

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
//执行第8行代码内部调用了onTouchEvent方法
D/liuyzz:TextLinerLayout:: onTouchEvent--- 
//因为子TextLinerLayout中onTouchEvent的返回默认值即false,所以大部分情况下第8行的值取决于onTouchEvent的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move==false
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---   

由打印结果得知:子View在Down事件中不处理事件,将会上传给TextLinerLayout的onTouchEvent事件,并且后续事件不再会传递给子View

当把TestButton中onTouchEvent方法中ACTION_MOVE事件返回false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==true

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---move==false
//这里的真假,取决于子View中move中返回的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move==false
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---up

由打印结果得知:虽然button的move事件不处理事件,但事件流已经开始往button中传递了,所以返回true、false都会传递给子View

当TestButton中onTouchEvent方法中ACTION_MOVE事件返回false,TextLinerLayout中dispatchTouchEvent的ACTION_MOVE中返回false时##

打印结果和只是TestButton中onTouchEvent方法中ACTION_MOVE事件返回false的结果一样

当把TextLinerLayout的dispatchTouchEvent中的Down值修改如下

只返回true,而不再调用super.dispatchTouchEvent(event)
case MotionEvent.ACTION_DOWN:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---down");
    return true;

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move==false
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---

由打印结果得知:在down中接收处理事件,则事件不会再往下传递到子View,也不会传递给自己的onInterceptTouchEvent、onTouchEvent方法,而在上面的move、up中进行了super.dispatchTouchEvent(event)调用,所以才会调用onTouchEvent方法

当把TextLinerLayout的dispatchTouchEvent中的值修改如下

case MotionEvent.ACTION_DOWN:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---down");
    return true;
case MotionEvent.ACTION_MOVE:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
    return true;
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---

由打印结果得知:把down、move都直接返回true时,onTouchEvent只会在up的时候被调用,因为默认up时会调用super.dispatchTouchEvent(event)

当把TextLinerLayout的dispatchTouchEvent中的Move值修改如下

只返回true,而不再调用super.dispatchTouchEvent(event)
case MotionEvent.ACTION_MOVE:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
    return true;
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==true

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---up

由打印结果得知:只拦截了move事件,其他事件还是会传到button中处理,而TextLinerLayout的onToucheEvent并没有被调用,说明这只是拦截了事件,并不是拦下处理事件,由 此可以推出,当在父View的move或者up中返回true,则父View只拦截当前事件,后续事件不拦截会继续传递到子View

当把TextLinerLayout的dispatchTouchEvent中的值修改如下

case MotionEvent.ACTION_DOWN:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---down");
    return break;
case MotionEvent.ACTION_MOVE:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
    return true;
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---up

由打印结果得知:只拦截了move事件,其他事件还是会传到button中处理,而TextLinerLayout的onToucheEvent并没有被调用,说明这只是拦截了事件,并不是拦下处理事件,而在up中事件又传递到了onTouchEvent中,由 此可以推出,当在父View的move或者up中返回true,则父View只拦截当前事件,后续事件不拦截会继续传递到子View

当把onInterceptTouchEvent修改如下

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---");
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---down");
            return true;
        case MotionEvent.ACTION_MOVE:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---move");
            break;
        case MotionEvent.ACTION_UP:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---up");
            break;
    }
    return super.onInterceptTouchEvent(ev);
}
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---down
//因为拦截了,所以直接调用自己的onTouchEvent
D/liuyzz:TextLinerLayout:: onTouchEvent---
//因为拦截了,所以这里的真假,取决于当前View的onTouchEvent中down中返回的值(默认返回false)
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onTouchEvent---
//因为拦截了,所以这里的真假,取决于当前View的onTouchEvent中move中返回的值
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move==false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---

当把TextLinerLayout的dispatchTouchEvent中的值和onInterceptTouchEvent修改如下

case MotionEvent.ACTION_MOVE:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
    return true;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---");
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---down");
            return true;
        case MotionEvent.ACTION_MOVE:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---move");
            break;
        case MotionEvent.ACTION_UP:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---up");
            break;
    }
    return super.onInterceptTouchEvent(ev);
}
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---down
D/liuyzz:TextLinerLayout:: onTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---

由打印结果得知:当Move事件返回true,TextLinerLayout的onToucheEvent并没有被调用,说明这只是拦截了Move事件,并不是拦下处理事件,但因为onInterceptTouchEvent进行拦截,所以在up事件中不会再传递到子View中

当修改代码如下

case MotionEvent.ACTION_MOVE:
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
    return true;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---");
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---move");
            return true;
        case MotionEvent.ACTION_UP:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---up");
            break;
    }
    return super.onInterceptTouchEvent(ev);
}
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---down
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down==true

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---up
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---up

由打印结果得知:虽然在拦截的move中返回true,但是在dispatchTouchEvent的move中返回了true,因为不会走拦截中的move事件,即事件在dispatchTouchEvent的move中被拦截,但是并没有走到onTouchEvent中去处理,当up时,事件正常传递

当代码修改成在dispatchTouchEvent的move中使用break 如下

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---");
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---move");
            break;
        case MotionEvent.ACTION_UP:
            Log.d("liuyzz:TextLinerLayout:", "dispatchTouchEvent---up");
            break;
    }
    return super.dispatchTouchEvent(event);
}


@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---");
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---move");
            return true;
        case MotionEvent.ACTION_UP:
            Log.d("liuyzz:TextLinerLayout:", "onInterceptTouchEvent---up");
            break;
    }
    return super.onInterceptTouchEvent(ev);
}
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---down
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---down
D/liuyzz:button:: dispatchTouchEvent---
D/liuyzz:button:: onTouchEvent---down==false

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---
D/liuyzz:TextLinerLayout:: onInterceptTouchEvent---move
//不清楚这里为什么会只调用一次button方法
D/liuyzz:button:: dispatchTouchEvent---

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
D/liuyzz:TextLinerLayout:: onTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---move
D/liuyzz:TextLinerLayout:: onTouchEvent---
.....

D/liuyzz:TextLinerLayout:: dispatchTouchEvent---
D/liuyzz:TextLinerLayout:: dispatchTouchEvent---up
D/liuyzz:TextLinerLayout:: onTouchEvent---

由打印结果得知:虽然在move中进行拦截,但是还是会走一下button的dispatchTouchEvent的方法(不清楚为什么),但是button的onTouchEvent不会走,剩下的都会走TextLinerLayout的方法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值