1. 程式人生 > >關於Android事件分發中onInterceptTouchEvent呼叫時機

關於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後把後續事件攔截的。