自定义View时requestDisallowIntercept

作者: zhangyugehu | 来源:发表于2017-09-12 18:06 被阅读88次

    在处理自定义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

    相关文章

      网友评论

        本文标题:自定义View时requestDisallowIntercept

        本文链接:https://www.haomeiwen.com/subject/xcncsxtx.html