View事件的分发拦截机制流程

1.View事件的分发机制

请想象一下生活中非常常见的现象:

假设你所在的学校,学校接到一份通知说领导要来视察。假设学校的校长级别最高,他下面有你的班主任老师,级别次之:最底层,就是干活的你,没有级别。现在为了应对领导的视察校长要把学校的门口公共卫生搞干净(这是一项任务)。校长把这一项任务安排给你的班主任,你的班主任把这项任务安排给了你。而好不容易你把活干完了,你就把任务交给了班主任,班主任觉得完成的不错,于是签了名字交给校长。这样一个任务就顺利的完成了。为了能够方便的了解整个事件的流程,我做了如下的设计:

校长----MyViewGroupA,最外层的ViewGroup.

班主任--MyViewGroupB,中间层的ViewGroup.

干活的你--MyView,在最顶层

整体效果图如下:


我们新建三个类 MyViewGroupA.java ,MyViewGroupB.java,MyView.java

MyViewGroupA.java:

<span style="font-size:12px;">public class MyViewGroupA extends LinearLayout {

    public MyViewGroupA(Context context) {
        super(context);
    }

    public MyViewGroupA(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroupA(Context context, AttributeSet attrs,
                        int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("xys", "ViewGroupA dispatchTouchEvent" + ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("xys", "ViewGroupA onInterceptTouchEvent" + ev.getAction());
       return super.onInterceptTouchEvent(ev);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("xys", "ViewGroupA onTouchEvent" + event.getAction());
        return super.onTouchEvent(event);
       // return true;
    }
}</span>


MyViewGroupB.java:

<span style="font-size:12px;">public class MyViewGroupB extends LinearLayout {

    public MyViewGroupB(Context context) {
        super(context);
    }

    public MyViewGroupB(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroupB(Context context, AttributeSet attrs,
                        int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("xys", "ViewGroupB dispatchTouchEvent" + ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("xys", "ViewGroupB onInterceptTouchEvent" + ev.getAction());
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("xys", "ViewGroupB onTouchEvent" + event.getAction());
        return super.onTouchEvent(event);
       // return true;
    }
}</span>


MyView.java:

<span style="font-size:12px;">import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs,
                  int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("xys", "View onTouchEvent" + event.getAction());
        return super.onTouchEvent(event);
   
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("xys", "View dispatchTouchEvent" + event.getAction());
        return super.dispatchTouchEvent(event);
    }

}</span>


我们分情况来比较

     1.1   先不修改任何返回值,点击一下View,log打印信息如下:


可以看见正常情况下,

事件的传递顺序是:

校长(MyViewGroupA)—班主任(MyViewGroupB)—你(View)。事件的传递顺序先执行dispatchTouchEvent()方法,再执行onInterceptEvent()方法。

事件的处理顺序是:

你(View)—班主任(MyViewGroupB)—校长(MyViewGroupA)。事件处理都是执行onTouchEvent()方法。

事件传递的返回值非常容易理解:True,拦截,不继续;False,不拦截,继续流程。

事件处理的返回值也类似:True,处理了,不用审核了:False,给上级处理。

初始情况下返回值都是False.

     1.2  假设校长觉得这项任务没必要找班主任,自己就可以完成。因此事件就被校长拦截了,即让MyViewGroupA的

onInterceptTouchEvent()方法返回true,我们再来看看log信息。


跟我们所想的一样,校长把所有的事情都干完了,没后面的人什么事了。

     1.3    假设班主任觉得这项任务没必要找你,自己就可以完成。因此事件就被班主任拦截了,即让MyViewGroupB的

onInterceptTouchEvent()方法返回true,我们再来看看log信息。

     

我们就可以知道,班主任把所有的事情都做完了,后面的你(MyView)就不需要干活 了。到此我们的事件的分发,拦截机制应该比较清楚了。

再来看看事件的处理:

    1.4  先来看那看底层的人民---你(MyView),当你处理完底层任务以后,需要上级的确认,所以你的处理事件返回false。但是有一天你不干了罢工了,也就不用报告上级 班主任了,所以直接返回true。即让onTouchEvent()方法返回true,点击view,让我们来看看log信息。


可以看出事件传递和以前一样,但是事件处理到你(MyView)就结束了。因为你返回true,不用向上级报告。

    1.5  如果你把完成的任务递交给班主任,但是班主任觉得你完成的不够好并没有把你做好的任务报告给校长。所以直接返回true。即让班主任的onTouchEvent()方法返回true,点击view,让我们来看看log信息。


     可以知道事件处理到班主任(MyViewGroupB)就结束了。

通过上面的几种情况分析,我们可以得出如下结论:

事件的传递顺序是:

校长(MyViewGroupA)—班主任(MyViewGroupB)—你(View)。事件的传递顺序先执行dispatchTouchEvent()方法,再执行onInterceptEvent()方法。

事件的处理顺序是:

你(View)—班主任(MyViewGroupB)—校长(MyViewGroupA)。事件处理都是执行onTouchEvent()方法。

事件传递的返回值非常容易理解:True,拦截,不继续;False,不拦截,继续流程。

事件处理的返回值也类似:True,处理了,不用审核了:False,给上级处理。

初始情况下返回值都是False。

上面我们只是对流程有个大概的了解,但是我们并没有从源码上面来分析为什么会有上面的流程?下节我们再来仔细研究源码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值