Android常见滑动冲突场景

  Android中常见的滑动冲突主要分为三种:
  1.外部滑动方向和内部滑动方向不一致
  2.外部滑动方向和内部滑动方向一致
  3.前两种的嵌套
  既然滑动冲突都有既定的规律,那么解决滑动冲突也肯定有通用的方法.

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

  在这种情形下,我们可以根据滑动距离(水平距离和垂直距离)来判断滑动方向,并且来决定是该由外部View来拦截还是由内部View来拦截,简单的来说就是根据水平距离和垂直距离的比较来决定由哪个View来拦截,如果垂直方向距离比较大,那么就由垂直方向的View来进行拦截,反之则有水平方向的View来拦截.
  具体实现主要有外部拦截和内部拦截两种方法.

外部拦截

  所谓外部拦截就是所有的点击事件都由父容器来进行拦截处理,如果父容器需要处理该事件就进行拦截,返回true,否则就返回false;
  外部拦截需要重写父容器的onInterceptTouchEvent()方法:
  

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;
        default:
            break;
    }
    mLastXIntercept = x;
    mLastYIntercept = y;
    return intercepted
}

  首先是ACTION_DOWN事件,该事件在父容器中必须不拦截,即返回false,因为如果一旦父容器拦截了ACTION_DOWN事件,那么ACTION_MOVE和ACTION_UP事件都会直接由父容器来处理,那么子View就无法处理想光的点击事件来.
  另外就是ACTION_UP事件也必须返回false,也就是不要拦截,因为如果父容器中ACTION_UP返回了true,也就是拦截了,那么会导致子VIew的ACTION_UP事件无法响应,同时,onClick事件就无法执行了.这是父容器拦截中比较特殊,因为一旦父容器进行了拦截,那么后续的事件也就交由它自己处理了.(还记得上一篇所讲的总经理,部门经理和程序员场景吗?)

内部拦截

  内部拦截就是所有的点击事件交由子View来处理,如果子View需要处理该事件就直接处理,否则才返回给父容器来处理.这种方法和Android的分发事件不太一样(子View不处理就相当于不处理了,不会返回给父容器),所以我们需要配合requestDisallowInterceptTouchEvent(阻止父view拦截点击事件)才能正常工作.
  

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(fasle);//拦截
            break;
        case MotionEvent.ACTION_UP:
            break;
        default:
            break;
    }
    mLastX = x;
    mLastY = y;
    return super.dispatchTouchEvent(evnet);
}

  需要注意的是,父元素要默认拦截除了ACTION_DOWN以外的其他事件,这样当子元素调用parent.requestDisallowInterceptTouchEvent(true);,父元素才能继续拦截所需的事件,原因主要是FLAG_DISALLOW_INTERCEPT这个标志位并不控制ACTION_DOWN,一旦父元素拦截了ACTION_DOWN,那么所有的事件就无法传递给子元素了.
  

public boolean onInterceptTouchEvent(MotionEvent event){
        if (event.getAction() ==MotionEvent.ACTION_DOWN)
            return false;
        return true;

  综上所述的话,比较建议使用外部拦截来处理常见的滑动冲突,而且这种做法是通用的,完全可以用来处理第二和第三种滑动冲突.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值