事件分发之结论篇

众所周知,从安卓1.5到现在的8.0已经经过了10个年头,然而很多人对事件分发有着既清楚又模糊的概念,面试时候说是可以大概说一下的,然后真正写自定义view的时候能熟练用的却不多,如果你对下面几个问题都泯然于心,那也就基本掌握其精髓了

1.onInterceptTouchEvent这方法的返回值对分发有何影响,何时被调用
2.getParent().requestDisallowInterceptTouchEvent();这方法是干嘛的,有可能不生效么
3.onTouchEvent在down,move,up阶段的返回值影响啥
4.onTouchEvent的cancel事件何时被触发?

首先看down事件:

比如当你在屏幕上点击一个textView的时候事件其实是传到activity的dispatchTouchEvent的,然后会传到phonewindow的decoview里,那DecorView其实是viewGroup,每个viewGroup都会调用他的dispatchTouchEvent方法,然后看是否onInterceptTouchEvent的返回值会true,如果是的话就自己处理,当然这个源码里这个返回值是与onInterceptTouchEvent和requestDisallowInterceptTouchEvent这两个相关联的,这里暂不讨论后者

假如在down的时候父view的onInterceptTouchEvent返回为true,那子view还能接收到么?

答案是不能,就是这个cycle内所有的事件都交给父view了,那父view还会调用onInterceptTouchEvent来每次拦截么,其实是不会的,就会一直调用父view的onTouchEvent来处理(这里onTouchEvent先默认都返回true)

那这样的话requestDisallowInterceptTouchEvent方法何时会被调用呢?

答案是永远不会,很简单,这个方法是在子view的ontouchEvent那里调用的,能调用子view的这个方法,首先要分发给子view,然后子 view才可以getparent.requestDisallowInterceptTouchEvent(true)请求父类不拦截,这样就会忽略父类的onInterceptTouchEvent的值,故我们写viewgroup的时候绝对不能在onInterceptTouchEvent的down事件返回true,这样子view完全接受不到事件了

第二种情况,当在down事件,返回false的时候,表明此次的down事件是分发给子view的onTouchEvent的down事件,子view的onTouchEvent的down事件一旦返回false,那表明子view处理不了此次的down,很简单此次事件会重新调父view的onTouchEvent,并以后的事件(move,up)不会调用onInterceptTouchEvent方法进行询问
那一般来说,子view的ontTouchEvent的down是返回true的

那是否这个cycle内的move和up也会给子view呢?

答案是不会的,因为父view要每次在dispatchTouchEvent事件中调用
onInterceptTouchEvent来询问是否要拦截,那既然子view的down事件返回true了,当接收到move事件时,他还是要询问一遍。

其次看move事件

这里分几种情况:
1.当父view的onInterceptTouchEvent返回true的时候,表示此事件的move要自己处理,那既然down返回的是false(是调用子view的ontouchEvent的),此时会发送一个cancel事件给子view(源码中有分发的代码,下篇说)

那如果move事件返回false,会给他的父view处理么

如果此时父view的move也是返回fase(ontouchEvent),这样的情况和down不同,当move事件无论返回true或者false ,都会有自己处理,不会在向上传递(既然down都没问题,move有问题,就不管了)

2.当父view的onInterceptTouchEvent返回false的时候,那很显然,会调用子view的ontouchEvent的move(返回值不受影响)

最后看up事件

up事件其实和move事件是一摸一样的,不受返回值的影响

最后说下请求父类不拦截的那个方法

主要是用在父类的onInterceptTouchEvent方法在move和up事件中返回了true,如果子view在ontouchEvent的down事件中调用了此方法(并返回true),那这个cycle内接下来的move和up事件,都不会调用父类的
onInterceptTouchEvent,默认给子view执行了

所以我们能回答刚开始的几个问题了

1.onInterceptTouchEvent通常是父类在dispatchTouchEvent里调用的方法一般在down时,为了能让子view不拦截此事件,返回false让响应子view的ontouchEvent,一旦此事件给子view处理了,每次的(move,up)
都会调用其方法进行询问,调用过子view的请求父类不拦截的代码除外

2,有可能不生效,因为这个方法是子view调用的,当父view在onInterceptTouchEvent在down时返回true时,子view调用也无效

3.onTouchEvent在down时候返回false,表示处理不了此事件,会抛给父view处理此事件(无论父view拦不拦截),父view处理时也不会调用onInterceptTouchEvent方法
在move和up时候返回false,因为down是true了,在分发的源码里并没有对move和up做处理,所以返回值只影响ontouchEvent也就是dispatchTouchevent,并不会产生事件缺损,这一点很多人都有不同的意见,等下篇分析源码时再说

4.子view的cancel事件
当你的down,move,up事件有一个不是自己执行的,是父view执行的,那就父view就会发一个cancel事件给子view(源码里可以看到)

总的结论就是这样,当然如果想看源码分析的,可以看这篇博客。
事件分发基础篇之源码分析篇

    原文作者:暴走的小青春
    原文地址: https://www.jianshu.com/p/1d6e45e2f544
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞