滑动冲突的两种处理方式

上一篇我们讲了事件分发的过程,这一篇我们将会通过改变事件分发的过程解决滑动冲突

滑动冲突的常见场景

image.png

举个例子 我们常见的ViewPager和ListView嵌套时候时会出现滑动冲突,下面我们来自己处理一下这种冲突。

外部拦截法

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

    boolean intercepted = false;
    int x = (int) ev.getX();
    int y = (int) ev.getY();
    final int action = ev.getAction() & MotionEvent.ACTION_MASK;
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            intercepted = false;
            //调用ViewPager的onInterceptTouchEvent方法初始化mActivePointerId
            super.onInterceptTouchEvent(ev);
            break;
        case MotionEvent.ACTION_MOVE:
            //横坐标位移增量
            int deltaX = x - mLastXIntercept;
            //纵坐标位移增量
            int deltaY = y - mLastYIntercept;
            //我们横向滑动的时候拦截,竖向滑动时交给listview自己去处理
            if (Math.abs(deltaX)>Math.abs(deltaY)){
                intercepted = true;
            }else{
                intercepted = false;
            }
            break;
        case MotionEvent.ACTION_UP:
            intercepted = false;
            break;
        default:
            break;
    }
    mLastXIntercept = x;
    mLastYIntercept = y;

    return intercepted;
}

内部拦截法

我们可以重写ListView的dispatchTouchEvent()方法

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

    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            //要求父view不要拦截事件
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        case MotionEvent.ACTION_MOVE:
            //水平移动的增量
            int deltaX = x - mLastX;
            //竖直移动的增量
            int deltaY = y - mLastY;
            //当水平增量大于竖直增量时,表示水平滑动,此时需要父View去处理事件,让父view拦截事件
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            break;
        default:
            break;
    }

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

通过这两种方式我们就能解决大部分的滑动冲突
下面我们再来看图1-3这种冲突


image.png

这种情况其实也是根据上面两种方式来处理,我们可以根据滑动区域,来判断是否需要把滑动事件拦截自己处理,所以具体情况具体分析。

大家只用掌握上述滑动冲突的解决套路,不论场景是不同方向,还是同方向,还是乱七八糟的堆加在一起,就用套路去解决,万变不离其宗。根据上述的外部拦截和内部拦截法,可以看出外部拦截法实现起来更加简单,而且也符合View的正常事件分发机制,所以推荐使用外部拦截法(重写父View的onInterceptTouchEvent,父View决定是否拦截)来处理滑动冲突

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容