3.4 View的事件分发机制(二)

ViewGroup的事件分发伪代码

public boolean dispatchTouchEvent(MotionEvent ev) {
    /*
    ACTION_DOWNA事件初始化
    由于一个完整的事件序列是以DOWN开始,以UP结束,
    所以如果是DOWN事件,那么说明是一个新的事件序列,所以需要初始化之前的状态。
    */
    if (action == ACTIONN_DOWN) {
        mFrstTouchTarge = null;
        FLAG_DISALLOW_INTERCEPT=false;
    }

    // 检查是否拦截
    boolean intercepted;
    if (action == ACTIONN_DOWN || mFrstTouchTarge != null) {
        // FLAG_DISALLOW_INTERCEPT一般通过子View的requestDisallowInterceptTouchEvent来设置。
        if (!FLAG_DISALLOW_INTERCEPT) {
            //当ViewGroup要拦截事件的时候,那么后续的事件序列都将交给它处理,而不用再调用onInterceptTouchEvent()方法了,所以该方法并不是每次事件都会调用的。
            intercepted = onInterceptTouchEvent(event);
        }else {
            intercepted=true;
        }
    }else{
        intercepted = true;
    }

    TouchTarget newTouchTarget = null;  // 1
    boolean alreadyDispatchedToNewTouchTarget = false;
    if (!canceled && !intercepted) {
        
        if (actionMasked == MotionEvent.ACTION_DOWN
                || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
                || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
            // ACTION_DOWN时
            final int childrenCount = mChildrenCount;
            if (newTouchTarget == null && childrenCount != 0) {
                // 有子View
                final View[] children = mChildren;
                for (int i = childrenCount - 1; i >= 0; i--) { 
                    
                    if (!canViewReceivePointerEvents(child)                
                            || !isTransformedTouchPointInView(x, y, child, null)) {  
                        // 是否在执行动画以及是否在该Veiw的点击区域内,否则continue
                        continue;
                    }
                    // 到这里说明找到了子View    
                    newTouchTarget = getTouchTarget(child);
                    
                    //把事件分发给子View
                    if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {  
                        newTouchTarget = addTouchTarget(child, idBitsToAssign);
                        // 如果分发给子View的分发返回的true,说明子View消耗掉了事件,alreadyDispatchedToNewTouchTarget设为true
                        alreadyDispatchedToNewTouchTarget = true;
                        break;
                    }
                }      
            }
        }
    }

    // 继续执行到这里
    if (mFirstTouchTarget == null) {
        // 如果没有找到子View,调用dispatchTransformedTouchEvent方法,第三个参数是null,则调用super的分发方法,也就是viewgroup自己消费
        handled = dispatchTransformedTouchEvent(ev, canceled, null,
                TouchTarget.ALL_POINTER_IDS);
    } else {
        // 如果找到子View
        TouchTarget target = mFirstTouchTarget;
        while (target != null) {
            if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
                // 子Veiw消耗掉了事件,则直接返回true。一定是Down,其他事件是不会进入上面的条件的。
                handled = true;
            } else {
                // 其他事件或者Down事件没有消耗,继续调用子View分发
                if (dispatchTransformedTouchEvent(ev, cancelChild,
                        target.child, target.pointerIdBits)) {
                    handled = true;
                }
            }
        }
    }

}
// 调子View分发的方法
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
            View child, int desiredPointerIdBits) {
    final boolean handled;
    if (child == null) {
        // 没有子View,调super,也就是View的分发方法(View 的分发方法和viewgroup的不同,没有拦截方法,会调用onTouchEvent方法)
        handled = super.dispatchTouchEvent(event);
    } else {
        // 有子View,调子View的分发方法,不管子View是View还是ViewGroup
        handled = child.dispatchTouchEvent(event);
    }
    return handled;
}

// 给mFirstTouchTarget赋值,他影响拦截方法
private TouchTarget addTouchTarget(View child, int pointerIdBits) {
    TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
    target.next = mFirstTouchTarget;
    mFirstTouchTarget = target;
    return target;
}

// 拦截的方法,默认返回false,我们可以重写该方法
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    return false; 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容