Android的事件分发(二)

来源:互联网 发布:ibm医疗大数据 编辑:程序博客网 时间:2024/05/22 22:48

首先推荐一篇小弟转发的博客事件的传递

非常有启发性的一篇文章

咱们接着前一篇讲,探一探onTouchEvent的底

由于我们希望事件最终交给EventView处理,那么我们来瞧一瞧EventView的onTouchEvent的返回值对事件分发的影响

情景一: EventView的各种假设

返回true

其他的所有方法都是默认的返回值

06-23 11:23:56.680: I/System.out(811): eventView---DOWN事件,自己处理
06-23 11:23:56.700: I/System.out(811): eventView---UP事件,自己处理

事件确实被EventView拿到了,他对整个点击事件做了处理

在ACTION_DOWN时返回false

     @Override    public boolean onTouchEvent(MotionEvent event) {        System.out.println("view处理事件");        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            System.out.println("eventView---DOWN事件,自己处理");            return false;            //break;        case MotionEvent.ACTION_MOVE:            System.out.println("eventView---MOVE事件,自己处理");            break;        case MotionEvent.ACTION_UP:            System.out.println("eventView---UP事件,自己处理");            break;        case MotionEvent.ACTION_CANCEL:            System.out.println("eventView---CANCEL事件,自己处理");            break;        default:            break;        }        return super.onTouchEvent(event);//在这里为true    }

此时,我在EventView上做了一个滑动动作

06-23 11:46:24.380: I/System.out(903): eventView---DOWN事件,自己处理
06-23 11:46:24.380: I/System.out(903): group_inner---DOWN事件,自己处理
06-23 11:46:24.560: I/System.out(903): group_inner---MOVE事件,自己处理
06-23 11:46:24.570: I/System.out(903): group_inner---MOVE事件,自己处理
06-23 11:46:24.860: I/System.out(903): group_inner---UP事件,自己处理

可以看到,由于在ACTION_DOWN的时候返回了false,这个事件会被向上传递,即Group_inner,并且父类,即Group_inner已经记住了你,后面的事件(指DOWN和UP之间的一系列事件)都不会传给你了,他会传给自己的onTouchEvent进行处理.

下面我们再来一个假设,假设所有的View和ViewGroup的onTouchEvent都返回false,事件最终会去哪呢?

06-23 12:00:43.200: I/System.out(1088): event_view---DOWN事件,自己处理

06-23 12:00:43.200: I/System.out(1088): group_inner---DOWN事件,自己处理

06-23 12:00:43.200: I/System.out(1088): group_outer---DOWN事件,自己处理

06-23 12:00:43.200: I/System.out(1088): Activity处理事件

06-23 12:00:43.280: I/System.out(1088): Activity开始分发事件

06-23 12:00:43.280: I/System.out(1088): Activity处理事件

06-23 12:00:43.290: I/System.out(1088): Activity开始分发事件

06-23 12:00:43.290: I/System.out(1088): Activity处理事件

事件最终传到了Activity,那么问题又来了,假如Activity的onTouchEvent也返回false呢?

结果和上面的一样,所以,事件最终都会被Activity消费掉

现在假设EventView返回super.onTouchEvent(event)

其实我们最终也只想知道一件事,到底是true还是false呢?

所以我们选择进入他的super.onTouchEvent中去看一看,也就是View.onTouchEvent

8321行这个位置
if (((viewFlags & CLICKABLE) == CLICKABLE ||                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)){                          // do something    return true;}return false;


根据代码,我们知道,如果这个View是可点击的,那么这个方法最终会返回true,否则,返回false那么,问题又来了,我们这个View究竟是不是可点的呢,答案是yes,由于水平有限,我无法从源码的角度给出解释,我是用View.isClickable测试出来的,如果各位有知道的,请告知为了更进一步的验证,我后面又 View.setClickable(false),这里返回的是false

结论一:如果事件传递到当前的方法,而该方法返回了false,那么这个事件会从当前向上传递,并且都是由上层的来接收,如果传递到上面的也返回这个事件就会消失,而且接收不到下一次事件。如果返回了true,则会接收并消费该事件.如果返回super.onTouchEvent(ev),即调用View.onTouchEvent()。

在我的前一篇博客中,我们已经考虑到一点,即dispatchTouchEvent的返回值对他是有影响的。例如dispatchTouchEvent如果返回true,那么事件是不会向下分发了,也不会调用该View的onTouchEvent,而是在该方法中直接被消费。如果大家看了我之前对dispatchTouchEvent返回值得分析时,也许会注意到一个方法onInterceptTouchEvent,以及他在什么时候被调用了。

我们不妨再回到分发事件的开始,即分发--拦截--处理。

我们注意到,如果dispatchTouchEvent直接返回true,或者false时,onInterceptTouchEvent是不会被调用到的,这个可以看看我在前一篇打印的日志,只有返回super.dispatchTouchEvent时才会被调用。

是时候来看一看onInterceptTouchEvent方法了,其实关于这个方法,在我翻译的那一片博客中,已经有较好的诠释了。这个方法的返回值其实是很好理解的,true表示拦截,false表示方形。

源码的注释:

1.Return true to steal motion events from the children and have them dispatched to this ViewGroup through onTouchEvent().  

2.The current target will receive an ACTION_CANCEL event, and no further   messages will be delivered here

第一句:返回true表示偷走子类的事件,后续的事件都会被转发到该ViewGroup的onTouchEvent中 

第二句:目标视图将会收到一个CANCEL事件,并且后面的事件(指一次动作)他不再收到 

 我们的实验又要开始了  除了改动代码,其他的都是默认返回值.在Group_inner的onInterceptTouchEvent中进行判断,如果是一个DOWN事件,拦截,其他的放行  

06-24 03:00:08.063: I/System.out(623): group_inner---DOWN事件,自己处理  

06-24 03:00:08.112: I/System.out(623): group_inner---MOVE事件,自己处理  

06-24 03:00:08.292: I/System.out(623): group_inner---UP事件,自己处理  

可以看到,Group_inner处理了所有的事件,那么,说好的CANCEL事件呢?

且看下面的分析 ,在Group_inner的onInterceptTouchEvent中进行判断,如果是一个MOVE事件,拦截,其他的放行 

 06-24 03:04:03.653: I/System.out(718): eventView---DOWN事件,自己处理 

 06-24 03:04:03.753: I/System.out(718): eventView---CANCEL事件,自己处理  

06-24 03:04:03.773: I/System.out(718): group_inner---MOVE事件,自己处理  

06-24 03:04:03.803: I/System.out(718): group_inner---MOVE事件,自己处理

  06-24 03:04:03.973: I/System.out(718): group_inner---UP事件,自己处理  

可以看到,第二个MOVE事件,被Group_inner截断的那个事件,转化成了CANCEL事件,传到了EventView,然后,后面的事件他再也没份了 。当然,这是安卓的一种机制,自己的理解就是,如果压根你从最开始都没接触到这个事件,我为什么还要告诉你这个事件已经取。

下面来看看官方文档的解释:

1.For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent()

2.If you return true from here, you will not receive any following events: the target view will receive the same eventbut with the action {@link MotionEvent#ACTION_CANCEL}, and all further events will be delivered to your onTouchEvent()method and no longer appear here.

第一句话:如果你返回了false,后续的事件首先会被传递到这儿(根据前面的结论,dispatchTouchEvent必须返回super.dispatchTouchEvent,然后被传递到目标的onTouchEvent()

第二句话:如果你返回了true,后续的事件将不会传递到该方法中,此时被拦截的事件会被转化成ACTION_CANCEL事件传给目标(多半是子孩子),后续的事件将会被传递到该视图的onTouchEvent().


下一篇将会讨论requestDisallowInterceptTouchEvent方法
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝不能用花呗怎么办 淘宝号给冻结了怎么办 淘宝买家号封了怎么办 拼多多商家盗图怎么办 被拼多多盗图了怎么办 淘宝盗用图片被投诉怎么办 淘宝别人盗用我的图片怎么办 淘宝盗图申诉原图过大怎么办 淘宝别人举报我盗用图片怎么办 淘宝卖家被投诉盗图怎么办 淘宝卖家被投诉卖假货怎么办 淘宝买到假货卖家不承认怎么办 被投诉盗图扣2分怎么办 拼多多盗淘宝图怎么办 微信视频清理了怎么办 牛仔短裤买大了怎么办 淘宝图片打开变大了怎么办 同城换公司社保怎么办 劳务不给交社保怎么办 好多工厂外包工不交社保怎么办 外包公司没有交社保怎么办 外包公司不给交社保怎么办 银行取100万现金怎么办 给老外发警告信后怎么办 照片上传是歪的怎么办 日亚不能直邮的怎么办 电话信息被卖了怎么办 被亚马逊跟卖了怎么办 玉米出芽后土壤不够湿怎么办 雨伞请输入授权码怎么办 网页放手机端后看不了怎么办 微信收款码存在违法行为怎么办 tst优惠码密码忘了怎么办 扩展器登录不上怎么办 微信学法小程序积分不更新怎么办 开发商不给办房产证怎么办 传淘宝产品规格不匹配怎么办 刚买的手机想退怎么办 空调主机空间不足不散热怎么办 lol网速快延迟高怎么办 4g手机延迟高怎么办