自定義View時requestDisallowInterceptTouchEvent()失效問題

在處理自定義View有事會使用requestDisallowInterceptTouchEvent(true)來屏蔽父類中的onInterceptTouchEvent()方法。但發(fā)現調用之后有時不起作用。查看源碼,確實requestDisallowInterceptTouchEvent()方法設置的mGroupFlags標志位是用來控制onInterceptTouchEvent()方法的調用。

ViewGroup中dispatchTouchEvent部分源碼

// 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();
}

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;
}

問題就出在了resetTouchState()這步上。

/**
 * Resets all touch state in preparation for a new cycle.
 */
private void resetTouchState() {
    clearTouchTargets();
    resetCancelNextUpFlag(this);
    mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
    mNestedScrollAxes = SCROLL_AXIS_NONE;
}

雖然我們設置了requestDisallowInterceptTouchEvent(true),但每次dispatchTouchEvent()調用時都會重置mGroupFlags標志位,所以在判斷disallowIntercept是只要是ACTION_DOWN事件時永遠是false。所以ACTION_DOWN被攔截了基本沒戲了,其他事件只能從mFirstTouchTarget != null上下手了。mFirstTouchTarget是在interceptedfalse時賦值的。所以讓onInterceptTouchEvent()ACTION_DOWN事件是返回false即可。所以可以集成該類,復寫其onInterceptTouchEvent()方法。

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            return false;
            break;
        default:
            return super.onInterceptTouchEvent(ev);
            break;
    }
}

這樣在其子類的onTouchEvent()方法中調用getParent().requestDisallowInterceptTouchEvent(true);就可以生效了。

參考博客
http://blog.csdn.net/jiwangkailai02/article/details/46666147
http://blog.csdn.net/u014623470/article/details/51658609

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容