View的滑动冲突

View的滑动冲突是View体系的核心章节

滑动冲突是怎么产生的呢?

  • 在界面中只要内外两层可以同时滑动,就会产生滑动冲突

如何解决滑动冲突呢?

  • 有固定套路,是什么呢????

常见的滑动冲突场景

  • 外部滑动方向和内部滑动方向不一致
  • 外部滑动方向和内部滑动方向一致
  • 以上两种情况嵌套???

滑动冲突的处理规则

  • 场景一:根据滑动是水平还是垂直来判断由谁来拦截事件
    根据滑动过程中两个点的坐标就可以得出是水平还是垂直滑动
    三种方法:
    • 1 角度,滑动路径和水平方向形成的夹角
    • 2 距离,水平方向和竖直方向的距离(水平方向的距离大就是水平否则是竖直)
    • 3 速度差,水平竖直方向上的速度
  • 场景2,3都要根据业务需求来处理

滑动冲突的解决方式

  • 外部拦截法
    所谓外部拦截法是指点击事件都先经父容器的拦截处理,如果父容器需要此事件就拦截,不需要就不拦截
    外部拦截法要重写父容器的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;//父容器需要返回true
            }else{
                intercepted = false;//父容器不需要返回false
            }

            break;
        case MotionEvent.ACTION_UP:
            intercepted = false;//必须返回false,如果是true,子元素无法接收到ACTION_UP事件,子元素的onClick事件无法触发,父容器比较特殊,一旦开始拦截任何事件,后续的事件都会由他处理,即使这里是false,也可以传递给父容器
            break;
        default:
            break;
        }
        mLastXIntercept = x;
        mLastIntercept = y;
        return intercepted;
    }

2 内部拦截法

  • 指父容器不拦截任何事件,所有事件都传递给子元素,如果子元素需要就消耗掉,否则交给父控件。
  • 需要配合requestDisallowInterceptTouchEvent方法才能正常工作
  • 需要重写子元素的dispatchTouchEvent方法
  • 父元素也要重写onIntercepTouchEvent方法,拦截除了ACTION_DOWN以外的其他事件(因为一旦拦截ACTION_DOWN,所有事件都无法传递到子元素中,内部拦截就不起作用了)
    子元素:
@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); //true代表不拦截,请求父控件不要拦截自己
            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = x - mLastX;
            int deltaY = y - mLastY;
            if(父类需要此类的点击事件){
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            break;

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

父元素:

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

http://blog.csdn.net/xyz_fly/article/details/37932989
http://blog.csdn.net/lvxiangan/article/details/9309927

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值