ViewGroup#DispatchTouchEvent总结——
2017-11-13 本文已影响15人
X_Sation
重新弄了一个项目,里面包含了几个版本的sdk源码,只有java代码,直接用idea导入就好,方便查看,github地址,点击查看
前段时间分析了android2.3的源码,今天分析一下android6.0的,变化挺大的,view#dispatchTouchEvent比较简单,就不记录了,viewgroup的比较复杂,为了防止以后忘了,在这里整理一下。
事件已经分发到某个viewgroup了
- DOWN事件进来,清空状态(包括disallowintercept标记)
- 为intercepted赋值
- DOWN事件,根据disallowintercept标记和onItercept(),决定intercepted的值
- mFirstTouchTarget不为空,也就是该事件不是down事件,并且这个ViewGroup的孩子中有孩子处理了之前的事件。跟上一条一样,根据disallowintercept标记和onItercept(),决定intercepted的值
- 不是以上两种情况,也就是非down事件,并且mFirstTouchTarget为空,也就是这个事件序列中,down已经被该ViewGroup处理,所以现在这个事件也是由这个ViewGroup处理,所以intercepted直接就是true
- 如果不拦截
- 如果是down
- 从孩子中找到可以接收事件的孩子,并且调用孩子的dispatchTouchEvent,也就是让他处理
- return true,也就是孩子处理了,那就把孩子赋值给mFirstTouchTarget(TouchTarget是一个包裹了View的对象),并且把一把局部变量alreadyDispatchedToNewTouchTarget设为true,表示该事件是down,并且已经找到了处理他的孩子
- return false,找其他孩子,如果有一个return true,就像上一步一样,如果全是false,那么mFirstTouchTarget不会被赋值,依旧是false,alreadyDispatchedToNewTouchTarget也是false
- 从孩子中找到可以接收事件的孩子,并且调用孩子的dispatchTouchEvent,也就是让他处理
- 如果是down
- 上面的逻辑处理完之后来,来到这里
- mFirstTouchTarget为空,表示,不管是down还是其他事件,总之就是没有孩子要处理,因为上一步中没有给mFirstTouchTarget赋值。所以直接让自己处理,调用super.dispatchtouchevent();
- 否则,该事件序列已经有孩子处理了,但是分两种情况
- 这个事件是down事件,孩子已经处理了,这个可以根据alreadyDispatchedToNewTouchTarget来决定,因为alreadyDispatchedToNewTouchTarget是局部变量,此时直接让handled为true即可
- 这个事件是非down事件,该事件序列都是让mFirstTouchTarget处理,所以该事件也是,所以调用mFirstTouchTarget.dispatchtouchevent(),让孩子处理,(但是如果最开始的intercepted是true了,这里分发给孩子的时候action就是cancle,事件就被取消了,而且mFirstTouchTarget会一直被赋值,赋值为下一个child,直到最后,成为空,这样,就会让viewgroup处理事件了)
- 这里孩子可能会返回true或者false
- return true,孩子已经处理
- return false,表示孩子不愿意处理,但是不同于上面第三节中的孩子不处理,第三节中,事件是down,孩子不处理,就让该viewgroup处理,而这里是非down事件,孩子不处理,事件就消失了,return false,那么上一级viewgroup也是return false,一路向上,最后就到activity的dispatchTouchEvent了