关于Android事件分发中onInterceptTouchEvent调用时机

首先,当一个down事件来临的时候,viewgroup的dispachTouchEvent中会清除所有的上一个手势的状态

// Handle an initial down.
if (actionMasked == MotionEvent.ACTION_DOWN) {
    // Throw away all previous state when starting a new touch gesture.
    // The framework may have dropped the up or cancel event for the previous gesture
    // due to an app switch, ANR, or some other state change.
    cancelAndClearTouchTargets(ev);
    resetTouchState();
}

关于事件拦截调用的源码:

// Check for interception.
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); // restore action in case it was changed
    } else {
        intercepted = false;
    }
} else {
    // There are no touch targets and this action is not an initial down
    // so this view group continues to intercept touches.
    intercepted = true;

}

流程:先判断是否是一个down事件或者是否有首次触摸目标,为false就是代表上一个down被自己消费了,所以这次肯定拦截下来自己处理。为true的话就是这个down事件第一次传递到该ViewGroup,然后获得一个disallowIntercept值,关于mGroupFlags中该位掩码的赋值在以下方法中发现

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
        // We're already in this state, assume our ancestors are too
        return;
    }

    if (disallowIntercept) {
        mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
    } else {
        mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
    }

    // Pass it up to our parent
    if (mParent != null) {
        mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
    }
}
该方法设置了当前ViewGroup及以上所有ViewGroup的不允许拦截状态掩码,但是未发现View和ViewGroup中有过调用,应该是给扩展类调用的。也就是说当我们没有特定需求的时候,ViewGroup的disallowIntercept状态都是false的,那么onInterceptTouchEvent()都会执行。即子控件响应了down动作后,只要没有调用requestDisallowInterceptTouchEvent方法,后续事件父控件都允许拦截。

通过代码测试,父控件把up事件拦截,子控件会处理到down和move,但是没有up触发不了onClick。

结论:没有请求父控件不拦截touch事件的时候,父控件式可以在子控件处理了down后把后续事件拦截的。




你可能感兴趣的:(Android)