美文网首页
3.5 View的滑动冲突(一)

3.5 View的滑动冲突(一)

作者: 武安长空 | 来源:发表于2016-06-22 16:22 被阅读46次

1. 常见滑动冲突场景

  • 外部滑动方向和内部滑动方向不一致
    如外部ViewPager左右滑动,内部ListView上下滑动
  • 外部滑动方向和内部滑动方向一致
    如ScrollView嵌套ListView,条件1ScrollView滚动,条件2ListView滚动
  • 以上两种混合

2. 滑动冲突解决方式一:外部拦截法

int mLastInterceptX = 0;
int mLastInterceptY = 0;
@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:
            // 这里必须返回false,因为这里如果父View拦截了,子View收不到后续事件,
            // 应该让子View拿到Down事件,父View拦截Move事件。
            intercepted = false;
            break;
        case MotionEvent.ACTION_MOVE:
            // 这里根据条件判断是否需要拦截
            if (父容器需要当前事件条件满足){
                intercepted = true;
            }else {
                intercepted = false;
            }
            break;
        case MotionEvent.ACTION_UP:
            // 这里返回false,因为up没什么意义了
            intercepted = false;
            break;
        case MotionEvent.ACTION_CANCEL:
            break;
    }
    mLastInterceptX = x;
    mLastInterceptY = y;
    return super.onInterceptTouchEvent(ev);
}

3. 滑动冲突内部拦截法

这种方法主要利用子元素的以下方法

getParent().requestDisallowInterceptTouchEvent(true);

重写子元素的dispatchTouchEvent方法

int mLastX,mLastY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    int x = (int) ev.getX();
    int y = (int) ev.getY();
    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            // True if the child does not want the parent to intercept touch events.
            // down时不希望父Veiw拦截,父View拦截后,后续事件无法传到子View中
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = x - mLastX;
            int deltaY = y - mLastY;
            if (父容器需要此类点击事件的条件满足){
                // false 子类希望父View拦截(disallowIntercept,不允许拦截,不拦截为true则不拦截,为false则拦截)
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_CANCEL:
            break;
    }
    mLastX = x;
    mLastY = y;
    return super.dispatchTouchEvent(ev);
}

父容器做如下修改

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN){
        // down时不拦截
        return false;
    }
    // 其他拦截
    return true;
}

相关文章

网友评论

      本文标题:3.5 View的滑动冲突(一)

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