simplebam

风来了,我要努力活下来...

关于B拦截了子视图C的Move事件B本身不消费,是否上交给上司处理呢?

这里需要引入一些小知识:
这里写图片描述

以下做了一个小实验:
1.activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.example.yueyue.myapplication.widgte.MyLinearLayout1
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--MyLinearLayout1不拦截MOVE事件但消费-->
    <!--MyLinearLayout0拦截MOVE事件不消费-->
    <com.example.yueyue.myapplication.widgte.MyLinearLayout0
        android:id="@+id/lyo_content"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@color/colorAccent"
        android:orientation="vertical">

        <com.example.yueyue.myapplication.widgte.MyCustomView
            android:id="@+id/cv_main"
            android:layout_width="110dp"
            android:layout_height="110dp"/>
    </com.example.yueyue.myapplication.widgte.MyLinearLayout0>

</com.example.yueyue.myapplication.widgte.MyLinearLayout1>

2.MainActivity重写了两个方法:

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i("xx", "MainActivity的dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("xx", "MainActivity的onTouchEvent");
        return super.onTouchEvent(event);
    }

3.MyCustomView的代码-仅消费Down事件(所以确定为事件的消费者)

public class MyCustomView extends View {

    private Paint paint1;
    private Paint paint2;

    public MyCustomView(Context context) {
        this(context, null);
    }

    public MyCustomView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyCustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        paint1 = new Paint();
        paint1.setColor(Color.GREEN);
        paint1.setStyle(Paint.Style.FILL);


        paint2 = new Paint();
        paint2.setColor(Color.YELLOW);
        paint2.setStyle(Paint.Style.FILL);

        //绘制外层矩形
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint1);
        //绘制内层矩形
        canvas.drawRect(10, 10, getMeasuredWidth() - 10, getMeasuredHeight() - 10, paint2);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean flag = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("xx", "MyCustomView的onTouchEvent--ACTION_DOWN" + event.getAction());
                flag = true;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("xx", "MyCustomView的onTouchEvent--ACTION_MOVE" + event.getAction());
                flag = false;
                break;
            case MotionEvent.ACTION_UP:
                Log.i("xx", "MyCustomView的onTouchEvent--ACTION_UP" + event.getAction());
                flag = false;
                break;
            default:
                break;

        }

        return flag;
    }


}

3.MyLinearLayout0-拦截事件的MOVE跟UP事件,但仅仅消费UP事件

public class MyLinearLayout0 extends LinearLayout {
    public MyLinearLayout0(Context context) {
        this(context, null);
    }

    public MyLinearLayout0(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout0(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean flag = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                Log.i("xx", "MyLinearLayout0的 onInterceptTouchEvent ACTION_MOVE" + ev.getAction());
                flag = true;
                break;
            case MotionEvent.ACTION_UP:
                Log.i("xx", "MyLinearLayout0的 onInterceptTouchEvent ACTION_UP" + ev.getAction());
                flag = true;
                break;
            case MotionEvent.ACTION_DOWN:
                Log.i("xx", "MyLinearLayout0的 onInterceptTouchEvent ACTION_DOWN" + ev.getAction());
                flag = false;
                break;
        }
        return flag;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean flag = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("xx", "MyLinearLayout0的onTouchEvent--ACTION_DOWN" + event.getAction());
                flag = false;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("xx", "MyLinearLayout0的onTouchEvent--ACTION_MOVE" + event.getAction());
                flag = false;
                break;
            case MotionEvent.ACTION_UP:
                Log.i("xx", "MyLinearLayout0的onTouchEvent--ACTION_UP" + event.getAction());
                flag = true;
                break;
            default:
                flag = false;
                break;
        }
        return flag;

    }
}

4.MyLinearLayout1不拦截任何事件,但消费ACTION_MOVE跟UP事件

public class MyLinearLayout1 extends LinearLayout {
    public MyLinearLayout1(Context context) {
        this(context, null);
    }

    public MyLinearLayout1(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyLinearLayout1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        Log.i("xx", "MyLinearLayout1的onInterceptTouchEvent--" + event.getAction());
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean flag = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("xx", "MyLinearLayout1的onTouchEvent--ACTION_DOWN" + event.getAction());
                flag = false;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("xx", "MyLinearLayout1的onTouchEvent--ACTION_MOVE" + event.getAction());
                flag = true;
                break;
            case MotionEvent.ACTION_UP:
                Log.i("xx", "MyLinearLayout1的onTouchEvent--ACTION_UP" + event.getAction());
                flag = true;
                break;
            default:
                flag = false;
                break;
        }
        return flag;

    }
}

实验结果:
这里写图片描述

I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–0
I/xx: MyLinearLayout0的 onInterceptTouchEvent ACTION_DOWN0
I/xx: MyCustomView的onTouchEvent–ACTION_DOWN0
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–2
I/xx: MyLinearLayout0的 onInterceptTouchEvent ACTION_MOVE2
I/xx: MainActivity的onTouchEvent
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–2
I/xx: MyLinearLayout0的onTouchEvent–ACTION_MOVE2
I/xx: MainActivity的onTouchEvent
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–2
I/xx: MyLinearLayout0的onTouchEvent–ACTION_MOVE2
I/xx: MainActivity的onTouchEvent
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–2
I/xx: MyLinearLayout0的onTouchEvent–ACTION_MOVE2
I/xx: MainActivity的onTouchEvent
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–2
I/xx: MyLinearLayout0的onTouchEvent–ACTION_MOVE2
I/xx: MainActivity的onTouchEvent
I/xx: MainActivity的dispatchTouchEvent
I/xx: MyLinearLayout1的onInterceptTouchEvent–1
I/xx: MyLinearLayout0的onTouchEvent–ACTION_UP1

这里可以做个小总结(事件必须要消费):
1.DOWN事件去确定消费者(可能是拦截,然后自己消费了该事件),然后MOVE以及UP分发过程中遇到消费者之后就不再向下传了,如果消费者不消费MOVE或者UP事件,那么就直接传给Activity去处理
2.分发过程中拦截的是DOWN事件(说明这时候还没有消费者),那么其本身的onTouch方法不消费,那么就上传给他的父亲(他父亲不消费,那么又上传给他爷爷),一层层上去直到找到消费者
3.分发过程中拦截的是MOVE事件或者UP事件,,如果其本身不消费MOVE或者UP事件,那么就直接传给Activity去处理,这里也解释了为什么拦截方法是在分发过程中进行拦截的,并且如果你在DOWN retrun true ,则DOWN,MOVE,UP子View都不会捕获事件(作为消费者,优先处理MOVE跟UP事件了);如果你在MOVE return true , 则子View在MOVE和UP都不会捕获事件。
这样设计的目的我觉得是MOVE事件太多了,如果像DOWN事件这样回传,系统负荷太重了


这里有几个大神写的好文章:
1.Android事件分发机制完全解析,带你从源码的角度彻底理解(上) - 郭霖的专栏 - CSDN博客 -两篇
2.Android ViewGroup事件分发机制 - Hongyang - CSDN博客 -张鸿洋的源码级别分析至今我还没有看懂
3.Android中事件分发机制 - qq97206858的博客 - CSDN博客

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/simplebam/article/details/78166629
文章标签: android
个人分类: 面试
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭