View的滑动冲突(通用解决方式)

View的滑动冲突

产生:界面中存在内外两层同时可以滑动的View

滑动冲突的场景

  • 场景一:外部滑动方向和内部滑动方向不一致
  • 场景二:外部滑动方向和内部滑动方向一致
  • 场景三:上面两种情况的嵌套

滑动冲突的处理规则

  • 根据滑动是水平滑动还是竖直滑动来判断到底由谁来拦截事件(适用场景一)
  • 当处于某种状态时需要外部View响应用户的滑动,而处于另外一种状态时则需要内部View来响应View的滑动(适用场景二和场景三)

滑动冲突的解决方式

外部拦截法和内部拦截法

  • 外部拦截法:事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截,如果不需要就不拦截。外部拦截法需要重写父容器的onInterceptTouchEvent方法

    //分别记录上次滑动的坐标(onInterceptTouchEvent)
    private int mLastXIntercept = 0;
    private int mLastYIntercept = 0;
    
    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:
    
                int deltaX = x - mLastXIntercept;
                int deltaY = y - mLastYIntercept;
    
                if(父容器需要当前点击事件){
                    intercepted = true;
                }else{
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
            default:
                break;
        }
    
        mLastXIntercept = x;
        mLastYIntercept = y;
    
        return intercepted;
    
    }
    

    上述代码是外部拦截法的典型逻辑,针对不同的滑动冲突只需修改“父容器需要当前点击事件”这个条件即可

  • 内部拦截法:指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就消费,否则就交由父容器进行处理。这种方法需要配合requestDisallowInterceptTouchEvent方法才能正常工作

    //分别记录上次滑动的坐标
    private int mLastX = 0;
    private int mLastY = 0;
    
    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;
            default:
                break;
        }
    
        mLastX = x;
        mLastY = y;
    
        return super.dispatchTouchEvent(event);
    
    }
    

    上述代码是内部拦截法的典型代码,面对不同的滑动策略时只需要更改“父容器需要此类点击事件”这个条件即可

    父元素所做的修改如下

    public boolean onInterceptTouchEvent(MotionEvent event){
        int action = event.getAction();
        if(action == MotionEvent.ACTION_DOWN){
            return false;
        }else{
            return true;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值