关于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方法用来对事...
  • u012165769
  • u012165769
  • 2015年12月29日 11:25
  • 872

事件分发,事件拦截,事件消费

1.      OnInterceptTouchEvent是viewGroup的方法,事件是从父控件一直向子控件传递的(寻找最终的ontouchevent响应者),但是OnInterceptTouch...
  • LAMP_zy
  • LAMP_zy
  • 2015年06月08日 10:47
  • 510

iOS父视图拦截子视图事件

给父视图添加手势,但是子视图的点击事件失效了,怎么办?我在写tableView 自定义cel中显示多张图片 可以左右滑动 我在cell里面放了一个collectionView, 点击tableView...
  • qq1051929447
  • qq1051929447
  • 2016年09月22日 11:37
  • 207

Android View事件分发、拦截、消费机制

日常开发中,我们经常会给各种控件设置点击、触摸事件。如果滑动有冲突,还得去解决滑动冲突,所以对View的事件分发(dispatchTouchEvent)、消费(onTouchEvent)、拦截(onI...
  • SilentWeek
  • SilentWeek
  • 2016年12月27日 17:52
  • 1590

汉诺塔的移动函数

汉诺塔的移动: 用Python编写move(n, a, b,c)函数,接收参数n,n表示3个柱子A、B、C中第1个柱子A的盘子数量,打印出把所有盘子从A借助B移动到C的方法; #期待输出:...
  • qq_35705269
  • qq_35705269
  • 2017年07月20日 08:36
  • 311

关于Python递归案例——汉诺塔的理解

刚开始学python,不是太能理解这道题的解法,直接在网上查找的案例代码,后来推了半天终于搞清楚了,故存于此处以免以后遗忘先上代码:def move(n, a, b, c): if(n == ...
  • dy_Beginner
  • dy_Beginner
  • 2017年12月09日 16:09
  • 57

Android开发知识(九):Android事件处理机制:事件分发、传递、拦截、处理机制的原理分析(下)

在前面的两个章节中,我们已经分析过关于Android事件处理机制的过程,特别是关于View的触摸、点击、长按之间的处理过程的分析,在本章节是我们分析Android事件处理机制的篇,我们将分析关于手指从...
  • lc_miao
  • lc_miao
  • 2017年10月18日 16:52
  • 10493

【Python自学】10.函数基础(下)

python自学递归函数与尾递归优化,汉诺塔练习
  • qq_23966673
  • qq_23966673
  • 2018年01月10日 00:06
  • 16

Android事件分发之子View驳回ViewGroup拦截原理分析

虽然网上关于这一块的博文很多,但是找了很久都没有找到比较全面的分析,所以想自己也开始写一些博客,一来让自己加深印象,二来希望能够给大家多多少少带来一些帮助。好了废话不多说,直接进入主题。Android...
  • gaokuanghua
  • gaokuanghua
  • 2016年09月06日 01:13
  • 168

while(a<b<c)怎么理解?

------关于while(a
  • LingXi__Y
  • LingXi__Y
  • 2017年06月19日 23:55
  • 238
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于B拦截了子视图C的Move事件B本身不消费,是否上交给上司处理呢?
举报原因:
原因补充:

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