ViewGroup.dispatchTouchEvent()分析
流程图:
拦截检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 final boolean intercepted;if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null ) { final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0 ; if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); } else { intercepted = false ; } } else { intercepted = true ; }
分析:
如果是ACTION_DOWN事件,则检查是否需要拦截。如果不是ACTION_DOWN事件,比如是ACTION_MOVE事件,则看mFirstTouchTarget的情况,若在之前的事件中有childView想处理touch事件,则mFirstTouchTarget不为空,即需要向下传递touch事件,这时候也需要检查是否需要拦截。
不是ACTION_DOWN事件, 并且mFirstTouchTarget为空,即不需要向下传递touch事件, 这时候可以直接设置intercepted=true,后续便不会向下传递事件。
不拦截,查找可以接收事件的子View
1 2 3 4 5 6 7 if (!canceled && !intercepted) { if (actionMasked == MotionEvent.ACTION_DOWN || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) || actionMasked == MotionEvent.ACTION_HOVER_MOVE) { } }
分析:
如果不是取消动作,并且不拦截事件,再如果是ACTION_DOWN事件,则查找一个可以接收这次事件的childView。若存在的话,则为mFirstTouchTarget赋值,不再为空。
只有添加到mFirstTouchTarget的childView才会收到后续的touch事件,childView需要在ACTION_DOWN事件中return true才会被添加到mFirstTouchTarget。
如何分发
//最后一组操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 if (mFirstTouchTarget == null ) { handled = dispatchTransformedTouchEvent(ev, canceled, null , TouchTarget.ALL_POINTER_IDS); } else { TouchTarget predecessor = null ; TouchTarget target = mFirstTouchTarget; while (target != null ) { final TouchTarget next = target.next; if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { handled = true ; } else { final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted; if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) { handled = true ; } if (cancelChild) { if (predecessor == null ) { mFirstTouchTarget = next; } else { predecessor.next = next; } target.recycle(); target = next; continue ; } } predecessor = target; target = next; } }
分析:
mFirstTouchTarget为空,即不需要往下传递,则最终会调用super.dispatchTouchEvent(), ViewGroup继承于View,即执行了View.dispatchTouchEvent();
对mFirstTouchTarget中的childView执行dispatchTransformedTouchEvent();
dispatchTransformedTouchEvent分析:
貌似就两种可能:
case 1: handled = super.dispatchTouchEvent(event);
case 2: handled = child.dispatchTouchEvent(event);