android 事件分发不是高深技术,却是做UI很重要的基础,以此复习记录。
分发规则
所谓分发事件的过程,就是传递MotionEvent的过程
关于MotionEvent需要记录一下的是:getX/Y和getRaxX/Y的区别,前者是返回相对于当前触摸的View的左上角的位置,而后者则是相对于手机屏幕左上角
事件分发的处理主要是在dispatchTouchEvent中进行,这个方法中会调用onInterceptTouchEvent来判断是否拦截某个事件:即这个事件是自己处理,还是传给子view的dispatchTouchEvent处理,没有子view的的单纯view直接自己处理。如果是自己处理则调用onTouchEvent方法。如果设置了OnTouchListener则先调用这个listener,至于后面还会不会调用onTouchEvent取决于listener返回的boolean,返回true则表示全都由listener处理,onTouchEvent不会被调用,反之则调用。而OnClickListener在onTouchEvent方法中调用,处于事件最末端。整个dispatch方法走完后需要得出结论,这个事件我是否已经搞定了,是否搞定是由上面几步的最终结果决定,或者由自己处理了,或者由子view处理了,如果都没处理(返回false),就返回给父view去处理了。
流程:viewgroup->dispatch->拦截->有OnTouchListener->onTouch->有OnClickListener->onClick:无OnClickListener->():无OnTouchListener->onTouchEvent:不拦截->子view的dispatch;循环
事件传递宏观:activity最先接收事件,然后传递给window对象(PhoneWindow类),然后传递给当前界面的底层容器DecorView(即activity的setcontentview的父容器)
下面抄写一些来自《android开发艺术探索》的结论:
(1)一个触摸会产生一个事件序列,即从手指down开始中间有许多move并以up结束
(2)一个view拦截了一个事件(down)后,之后的事件序列都会交到这个view
(3)某个view的onInterceptTouchEvent决定拦截某个事件后就不会再次调用了,然后拦截的后续事件序列直接都给这个view处理
(4)一个view拦截了事件,真正处理时不消耗down事件的话,即onTouchEvent方法返回false,那后续事件就不再交给他处理了,而是交给父view处理,即拦截一个事件就要把这个事件消耗,不然就不能真正处理这个事件序列
(5)*如果一个view只消耗了down事件而不消耗后续事件,那这个view还能继续收到后续事件,但是这些不处理的事件就会消失并最终由activity处理
(6)viewgroup默认不拦截任何事件
(7)单纯view没有onInterceptTouchEvent,有事件直接调用onTouchEvent
(8)一般单纯view都是会消耗事件的,他们的onTouchEvent返回true。除非clickable和longclickable都是false
(9)view的disable不影响(8)的结论