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

原创 2017年10月06日 19:42:27

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

以下做了一个小实验:
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博客

版权声明:本文为博主原创文章,未经博主允许不得转载。

首先是点击事件在不同的布局层次中传递的。 理解Down事件再哪个层次被消费(拦截),后续的Move、Up的点击事件如何传递。 其中ViewGroup中onInterceptTouchEvent方法

首先是点击事件在不同的布局层次中传递的。理解Down事件再哪个层次被消费(拦截),后续的Move、Up的点击事件如何传递。其中ViewGroup中onInterceptTouchEvent方法用来对事...

深入理解Oracle索引(7):用实验数据观察从B-tree索引→复合索引→Bitmap索引所消费的CPU和I/O

环境:sys@ORCL> !sqlplus -v SQL*Plus: Release 10.2.0.1.0 - Production sys@ORCL> !uname -a Linux Thin...

IP地址分类/IP地址10开头和172开头和192开头的区别/判断是否同一网段(A、B、C三类地址)

IP地址分类/IP地址10开头和172开头和192开头的区别/判断是否同一网段 简单来说在公司或企业内部看到的就基本都是内网IP,ABC三类IP地址里的常见IP段。 每个IP地址都包含两部...

10.A、B、C、D、E、F、G、H、I、J 共10名学生有可能参加本次计算机竞赛,也可能不参加。因为某种原因,他们是否参赛受到下列条件的约束:

package s5; public class test10 {     public static void main(String[] args) {         // TOD...

【HDU5579 2015上海赛区G】【超级大讨论】Game of Arrays a[]+b[]+c[]有些位置可以减一,状态是否可能达成

Game of Arrays Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) T...

hrbust1996 是否能找到三个数满足等式A[i]+B[j]+C[k]=X【hash模板】

http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1996 一定要用哈希表才能过,连map都不行。。 ...
  • cacyth
  • cacyth
  • 2016年02月23日 20:51
  • 612

lesson 6:写一个方法void triangle(int a,int b,int c),判断三个参数是否能构成一个三角形。

题目: 写一个方法void triangle(int a,int b,int c),判断三个参数是否能构成一个三角形。如果不能则抛出异常IllegalArgumentException,显示异常信息:...

给定一个n个整数的数组S,是否存在S中的4个数,使得a + b + c + d = target。 在数组中找出所有唯一的四元组,给出目标的总和。

本题源自LeetCode ------------------------------------------ 思路1 :回溯法 超时 代码; vector > fourSum(vecto...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于B拦截了子视图C的Move事件B本身不消费,是否上交给上司处理呢?
举报原因:
原因补充:

(最多只允许输入30个字)