view的滑动冲突解决方案

一、常见的滑动冲突场景

1.外部滑动方向和内部滑动方向不一致

2.外部滑动方向和内部滑动方向一致

3.上面两种情况的嵌套

二、滑动冲突处理的原则

场景1的处理原则是:当用户左右滑动时,需要让外部的view拦截点击事件,当用户上下滑动时,需要让内部的view拦截点击事件。场景2和场景3比较特殊,无法如同场景1一样原则的处理冲突,需要在业务上寻找突破点。比如业务上规定:当处于某种状态时需要外部View响应用户的滑动,而处于另一种状态时则需要内部View来响应View的滑动,根据这种业务上的需求我们也能得出相应的处理规则,有了处理规则同样可以进行下一步处理。

三、滑动冲突的解决方式

1.外部拦截法

外部拦截法是指点击事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截 ,如果不需要此事件就不拦截。代码示例如下:

/**
     * 针对不同的滑动冲突,只需要修改父容器需要当前点击事件这个条件既可,
     * 其他均不需要做修改并且也不能修改
     * @param event
     * @return
     */

    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;
                break;
            case MotionEvent.ACTION_MOVE:
                if(父容器需要当前事件点击){
                    intercepted = true;
                }else {
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;;
        }
        mLastXIntercepted = x;
        mLastYIntercepted = y;
        return intercepted;

    }

2.内部拦截法

内部拦截法是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器进行处理,这种方法和Android中的事件分发机制不一致,需要配合requestDisallowInterceptTouchEvent方法才能正常工作,使用起来比外部拦截法稍显复杂。示例代码如下:

/**
     * 当面对不同的滑动策略时只需要修改里面的条件即可,其他不需要做改动
     * 而且也不能有改动
     * @param event
     * @return
     */
    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;
                if(父容器需要此类点击事件){
                    parent.requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                
                break;;
        }
        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);

    }
原文地址:https://www.cnblogs.com/lushiju/p/5785938.html