Skip to content
  1. 滑动冲突的分类
  2. 滑动的处理规则
  3. 滑动冲突的解决方式

常见的滑动冲突场景

  1. 外部布局的滑动方向和内部布局的滑动方向不一致
  2. 外部滑动方向和内部滑动方向一致
  3. 上面两种情况的嵌套

场景一:外部控件左右滑动,内部控件上下滑动:类似ViewPager嵌套Fragment(ListView) 场景二:类似ScrollView嵌套ListView image.png

滑动冲突的处理规则

场景一:滑动的角度、距离差和速度差 场景二:业务的划分

滑动冲突的解决方式

  1. 外部拦截法

事件先经过父容器的拦截处理,重写父容器的onInterceptTouchEvent方法

  1. 内部拦截法

重写子元素的dispatchTouchEvent方法

外部拦截法

java
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 (父容器需要拦截的事件规则) {
            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;
}

内部拦截法

父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器进行处理。

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

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        parent.requestDisallowInterceptTouchEvent(true);
        break;
    }
    case MotionEvent.ACTION_MOVE: {
        int deltaX = x - mLastX;
        int deltaY = y - mLastY;
        Log.d(TAG, "dx:" + deltaX + " dy:" + deltaY);
        if (父容器需要当前点击事件) {
            parent.requestDisallowInterceptTouchEvent(false);
        }
        break;
    }
    case MotionEvent.ACTION_UP: {
        break;
    }
    default:
        break;
    }

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