Android 事件拦截/分发机制 (图解+代码)

一、介绍

Android为触摸事件封装了一个类MotionEvent,其实OnTouchEvent的一个参数就是MotionEvent

MotionEvent中封装了触摸点坐标、点击事件类型等

Android中的View可以放在一个ViewGroup中,这个ViewGroup又放在另一ViewGroup中等等,一层层嵌套起来,同一个触摸事件,View和父ViewGroup都想要处理,我们应该传给谁呢,此时就需要事件拦截机制

二、举例说明

完整的事件流程

  • 现在总经理ViewGroupA接到任务X,于是安排部长ViewGroupB去做,
  • ViewGroupB又把任务X交给底层的员工View来做。
  • 当员工View完成任务后,会向部长ViewGroupB报告,
  • 部长ViewGroupB收到报告,又可以向总经理ViewGroupA报告

这就是一个完整的事件流程

    事件传递顺序:        ViewGroupA    ->    ViewGroupB    ->    ViewC

    事件处理顺序:        ViewC    ->    ViewGroupB    ->    ViewGroupA 

    事件传递返回值:    true:拦截,不继续传递    false:不拦截,继续传递

    事件处理返回值:    true:处理了,不上报       false:处理了,但上报

    其实super.onTouchEvent(event)也是false的效果


事件拦截机制:

一系列打断上面完整事件流程的问题都属于事件拦截机制,如下几种情况:

  • 总经理ViewGroupA接到任务X,发现很简单,于是自己完成,没有交给部长B来做
  • 部长ViewGroupB接到员工的报告,发现不用总经理处理,于是独自处理
  • 员工View完成任务,不想上交任务报告,选择自己处理等


对于ViewGroupA重写一下三个方法

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e(TAG, "ViewGroupA onTouchEvent " + event.getAction() );
        return super.onTouchEvent(event);
    }

ViewGroupB与ViewGroupA类似

对于ViewC给出一下两个方法

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e(TAG, "ViewC dispatchTouchEvent: " + ev.getAction() );
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e(TAG, "ViewC onTouchEvent: " + event.getAction());
        return super.onTouchEvent(event);
    }

可以看出ViewGroupView多了一个方法onInterceptTouchEvent,此方法便是事件拦截的核心


之后我们点击C,会与如下日志:


所以可以得出

事件传递顺序:ViewGroupA    ->    ViewGroupB    ->    ViewC

事件处理顺序:ViewC    ->    ViewGroupB    ->    ViewGroupA 

其中

事件传递返回值:    true:拦截,不继续传递    false:不拦截,继续传递

事件处理返回值:    true:处理了,不上报       false:处理了,但上报


整个事件的流程如下:onInterceptTouchEvent是事件的核心处理方法


举几个图:

1.ViewGroupA把事件传递拦截下来

总经理A发现任务简单,自己处理,没有安排下属,即让ViewGroupAonInterceptTouchEvent返回true

日志:


流程:


2.ViewGroupB把事件传递拦截下来

部长B把事件拦截下来,自己处理,即让ViewGroupBonInterceptTouchEvent返回true

日志:


流程


3.ViewC把事件拦截下来

员工最开始要上上级汇报,所以一直返回false,现在让onTouchEvent返回true,自己处理

日志:


流程:


4.ViewGroupB把事件处理结果拦截下来

当员工C把报告上交,部长B发现报告有错误,自己处理,即让ViewGroupBonTouchEvent返回true

日志:


流程:






评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amarao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值