Android view 滑动事件冲突解决方法(理论篇)

1.外部拦截法:
通过父容器拦截处理,如果父容器需要就拦截,如果父容器不需要就不拦截交给子view;主要是修改父容器的 onInterceptTouchEvent 方法,伪代码如下:

@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 (父容器需要事件) {
                intercepted = true;
            } else {
                intercepted = false;
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            intercepted = false;
            break;
        }
    }
    return intercepted;
}

说明:

  • ACTION_DOWN 这个事件里父容器必须返回 false,即不拦截ACTION_DOWN事件,因为一旦拦截了那么后续的 ACTION_MOVE、ACTION_UP都由父容器去处理,事件就无法传到子view了
  • ACTION_MOVE 事件可以根据需要来进行拦截或者不拦截
  • ACTION_UP 这个事件必须返回false

2.内部拦截法
内部拦截只父容器不拦截任何事件,所有事件都传给子view,如果子view需要则消耗掉事件,否则交给父容器处理;主要是修改子view的 dispatchTouchEvent方法,伪代码如下:

@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: {
            if (父容器需要此类事件) {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            break;
        }
    }
    return super.dispatchTouchEvent(ev);
}

然后父容器需要做的改动如下:

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

注明:
如上代码,首先父容器拦截ACTION_DOWN 以外的其他事件,因为ACTION_DOWN 事件不受 FLAG_DISALLOW_INTERCEPT这个标记的控制,所以一旦父容器拦截了ACTION_DOWN 事件那么所有的事件都无法传到子view中去了,这样内部拦截法就不起作用了;

你可能感兴趣的:(android,事件冲突)