滑動事件衝突

一般分三種:
滑動方向一致導致的衝突
滑動方向不一致導致的衝突
滑動方向的各種疊加導致的衝突
解決方案分兩種:
外部攔截法
由外層父容器來處理,在父容器的onInterceptTouchEvent中決定是否需要攔截
內部攔截法
由內部子容器處理,在子容器中的dispatchTouchEvent中通過requestDiallowInterceptTouchEvent來申請父容器不攔截。
外部攔截
在父容器的onInterceptTouchEvent中決定是否需要攔截。
下面的父容器判斷:水平方向大於豎直方向,則攔截

if (Math.abs(deltaX) > Math.abs(deltaY)) {
    intercepted = true;
} else {
    intercepted = false;
}

只需要根據需求改變判斷的條件即可,完整代碼:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean intercepted = false;
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        intercepted = false;
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
            intercepted = true;
        }
        break;
    }
    case MotionEvent.ACTION_MOVE: {
        int deltaX = x - mLastXIntercept;
        int deltaY = y - mLastYIntercept;
        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            intercepted = true;
        } else {
            intercepted = false;
        }
        break;
    }
    case MotionEvent.ACTION_UP: {
        intercepted = false;
        break;
    }
    default:
        break;
    }

    Log.d(TAG, "intercepted=" + intercepted);
    mLastX = x;
    mLastY = y;
    mLastXIntercept = x;
    mLastYIntercept = y;

    return intercepted;
}

內部攔截
內部攔截是子容器請求父容器不攔截的做法。需要配合requestDisallowInterceptTouchEvent使用。父容器也要稍微做些變動,相對來說複雜了點。

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        mHorizontalScrollViewEx2.requestDisallowInterceptTouchEvent(true);
        break;
    }
    case MotionEvent.ACTION_MOVE: {
        int deltaX = x - mLastX;
        int deltaY = y - mLastY;
        Log.d(TAG, "dx:" + deltaX + " dy:" + deltaY);
        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            mHorizontalScrollViewEx2.requestDisallowInterceptTouchEvent(false);
        }
        break;
    }
    case MotionEvent.ACTION_UP: {
        break;
    }
    default:
        break;
    }

    mLastX = x;
    mLastY = y;
    return super.dispatchTouchEvent(event);
}

上面例子中,若水平方向上大於垂直方向,則交由父容器來處理,其他情況都有字容器來處理。所以父容器需要變動:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
        return false;
    } else {
        return true;
    }
}

變動:若是ACTION_DOWN則不攔截,也不能攔截。其他時候都要攔截。這樣只有在子容器請求父容器不攔截的時候才交由子容器來處理點擊事件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章