Android 事件分发机制---move、up事件源码理解

来源:互联网 发布:猎上网怎么样知乎 编辑:程序博客网 时间:2024/06/05 20:27

现在,我们接着分析下Move、Up的事件分发流程:

一、Move事件分发:
1、Activity依旧会将move事件,交给最顶层的ViewGroup分发处理,还是分析dispatchTouchEvent()方法
部分代码进行省略:
public boolean dispatchTouchEvent(MotionEvent ev) {
   ...

    boolean handled = false;
    if (onFilterTouchEventForSecurity(ev)) {
        final int action = ev.getAction();
        final int actionMasked = action & MotionEvent.ACTION_MASK;

        if (actionMasked == MotionEvent.ACTION_DOWN) {
            cancelAndClearTouchTargets(ev);
            resetTouchState();
        }

        final boolean intercepted;
        if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {//-------A:后续move、up事件被拦截
           ...
        } else {
            intercepted = true;//-----B:拦截
        }
 
        if (intercepted || mFirstTouchTarget != null) {
            ev.setTargetAccessibilityFocus(false);
        }

        final boolean canceled = resetCancelNextUpFlag(this) || actionMasked == MotionEvent.ACTION_CANCEL;

        final boolean split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0;
        TouchTarget newTouchTarget = null;
        boolean alreadyDispatchedToNewTouchTarget = false;
        if (!canceled && !intercepted) {//-----C:intercept = true进不去
          .......省略代码
        }

       
        if (mFirstTouchTarget == null) {//-----D:用于判断move/up事件分发
           
            handled = dispatchTransformedTouchEvent(ev, canceled, null,
                    TouchTarget.ALL_POINTER_IDS);//-----E:该代码其实是将事件交由自己的onTouchEvent()方法处理
        } else {
          
            TouchTarget predecessor = null;
            TouchTarget target = mFirstTouchTarget;
            while (target != null) {
                final TouchTarget next = target.next;
                if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {//----F:进不去,上面设置alreadyDispatchedToNewTouchTarget=false

                    handled = true;
                } else {
                    final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
                    if (dispatchTransformedTouchEvent(ev, cancelChild,target.child, target.pointerIdBits)) {//-----G:用于直接将后续事件分发给子类处理
                        handled = true;
                    }
                    if (cancelChild) {
                        if (predecessor == null) {
                            mFirstTouchTarget = next;
                        } else {
                            predecessor.next = next;
                        }
                        target.recycle();
                        target = next;
                        continue;
                    }
                }
                predecessor = target;
                target = next;
            }
        }

        if (canceled
                || actionMasked == MotionEvent.ACTION_UP
                || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
            resetTouchState();
        } else if (split && actionMasked == MotionEvent.ACTION_POINTER_UP) {
            final int actionIndex = ev.getActionIndex();
            final int idBitsToRemove = 1 << ev.getPointerId(actionIndex);
            removePointersFromTouchTargets(idBitsToRemove);
        }
    }

    if (!handled && mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onUnhandledEvent(ev, 1);
    }
    return handled;
}

总结:
1.当最顶级的ViewGroup执行dispatchTouchEvent()分发事件时,代码 A 因为不是Down事件,那么intercepted值为true,也就是代码B处。接着到代码C处if语句进不去。因为代码A未执行,左右不会执行onInterceptTouchEvent()方法,也就是说,除了Down事件会执行onIntercepterTouchEvent()方法,后续的Move、Up事件都不会进入到onInterceptTouchEvent()方法。
2.分析代码 D :如果Down事件没有找到TargetView,那么mFirstTouchTarget = null;那么事件则会直接交给自己同级的onTouchEvent()方法处理。如果Down事件有View消费了,那么if语句就会执行到代码 G处的判断。
3.代码 G处:其实就是一直将Move事件,向子类分发;也就是将上面的dispatchTouchEvent()方法再次执行一次,直到找到最终消费了Down事件的View为止。将Move事件交由该View处理。

二、Up事件,其实和move事件分发流程一致。
三、onTouchEvent()方法源码解读,可以参考这篇链接:http://blog.csdn.net/lmj623565791/article/details/38960443。
原创粉丝点击