自定义views Android开发Android进阶之旅

自定义View时requestDisallowIntercept

2017-09-12  本文已影响88人  zhangyugehu

在处理自定义View有事会使用requestDisallowInterceptTouchEvent(true)来屏蔽父类中的onInterceptTouchEvent()方法。但发现调用之后有时不起作用。查看源码,确实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

上一篇 下一篇

猜你喜欢

热点阅读