安卓事件拦截机制分析

本文通过比喻和示例代码详细解析了安卓事件传递机制。从顶层布局到最底层控件,层层递进地展示了事件如何被传递、拦截及处理的过程,并通过实际案例演示了这一机制。

开发常见的问题是,当希望控件响应某个事件时,其父View会将其拦截掉的尴尬局面,例如ViewPager会把每个page的横向滑动事件拦截掉,如果希望page里面的view可以横向滑动,而viewpage不跟着滑动就好了

面对这个问题,先来了解一些安卓的事件拦截机制,掌握其大概的流程,就可以针对具体的业务玩转事件拦截了。

先打个比方

公司里面有三层,第一层是总经理,第二层是部门经理,第三层是最底层的你。

某一天董事会让总经理分配一下任务,按照常规流程,总经理接到任务后,先把任务拆分,分配到各个部门经理,部门经理们接受任务后,再拆分,分配到最底层的劳动者,也就是你啦。你干完任务之后呢,向部门经理汇报,部门经理觉得满意,就签上自己的名字,再把任务完成的结果汇报给总经理,总经理最后审查,宣布任务完成。整个任务下来,先是由顶层往下传递,底层完成后,再反馈给顶层。代码也是来源于生活,这种模式也被应用于安卓的事件传递,处理机制中。

没错,总经理就是最顶层的布局,部门经理就是中间层的布局,你就是最底层的控件。当顶层捕获到一个事件时,会把这个事件一级一级的传递下去,直到底层控件接收到并处理掉,处理完之后再向上级反馈。

下面通过demo代码来演示这个机制

先创建3个自定义的控件ViewGroupA,ViewGroupB,MyView,继承于RelativeLayout 

重写三个方法


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

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

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

其他两个类也类似,就不写出来了

布局效果如下图

 

 

 

 

221813_8q3a_2335739.png

点击MyView

打印日志如下:

222058_p5kg_2335739.png

正常顺序:总经理(ViewGroupA)->部门经理(ViewGroupB)->你(MyView)

先调用dispatchTouchEvent,再调用onInterceptTouchEvent,最后调用onTouchEvent,

事件拦截(dispatchTouchEvent,onInterceptTouchEvent)

返回true,拦截,不继续,返回false,不拦截,继续传递

事件处理(onTouchEvent)

返回true,处理了,不用审核,返回false,没处理,返回上级处理

事件拦截主要关注的是onInterceptTouchEvent,虽然dispatchTouchEvent先被调用,但是一般情况下不用管它,如果我们让ViewGroupA的onInterceptTouchEvent返回true,表示拦截这个事件,继续点击MyView,日志如下

223732_a1IW_2335739.png

点击myView,但是由于ViewGroupA已经拦截了,所以事件不会传递下去,直接有ViewGroupA全部处理,就好比如总经理觉得这个任务比较简单,一个人可以搞定了,就不会把任务分配下去,这次我们让部门经理来做一次好人,在最开始的修改上让GroupViewB的拦截方法,返回true,日志如下

224220_Kzlg_2335739.png

作为底层的你就不会接受到任务,因为在任务分配到部门经理的时候,就被拦截了,部门经理完成任务,向上级汇报就好了。

如果父布局把整个事件都拦截下来了,子控件将收不到任何事件,这种情况在项目中是比较少见的,一般父布局只会拦截掉部分类型的事件,一般不会拦截ACTION_DOWN,这是一切事件的开端,拦截的话,子控件就不能接受到任何事件,更何况打断父布局拦截事件呢

 

 

 

 

 

转载于:https://my.oschina.net/carbenson/blog/863045

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值