View的滑动冲突处理方法

Feb 4, 2016


外部拦截法

父容器不拦截 ACTION_DOWN 事件,否则 ACTION_MOVE 和 ACTION_UP 都会由父容器处理, 在 ACTION_MOVE 只对要处理的事件返回 true, 在 ACTION_UP 也要返回 false。

private int mLastXIntercept;
private int mLastYIntercept;

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean intercepted = false;
    int x = (int) ev.getX();
    int y = (int) ev.getY();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            intercepted = false;
            break;
        case MotionEvent.ACTION_MOVE:
            if (interceptEvent(ev)) {
                intercepted = true;
            } else {
                intercepted = false;
            }
            break;
        case MotionEvent.ACTION_UP:
            intercepted = false;
            break;
        default:
            break;
    }
    mLastXIntercept = x;
    mLastYIntercept = y;
    return intercepted;
}

/* 父容器需要当前的点击事件 */
private boolean interceptEvent(MotionEvent ev) {
    return true;
}

内部拦截法

子 View

private int mLastX;
private int mLastY;

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    int x = (int) ev.getX();
    int y = (int) ev.getY();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        case MotionEvent.ACTION_MOVE:
            int detailX = x - mLastX;
            int detailY = y - mLastY;
            if (父容器需要的点击事件) {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            break;
    }
    mLastX = x;
    mLastY = y;
    return super.dispatchTouchEvent(ev);
}

父容器

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        return false;
    } else {
        return true;
    }
}