作为android开发人员,你一定遇到过滑动冲突问题,比如说,在水平ViewPager中嵌套ScrollView,然后在SrollView中嵌套一个水平可滑动的控件,这个时候就出现了滑动冲突,系统无法判断用户是左右滑动ViewPager还是水平滑动控件,而我们的需求是要求在操作水平控件的时候,其父容器不作出任何反应,也就是说,父容器不对点击事件做出拦截。那么怎么实现这个呢?在这里给大家提供两种方法,外部拦截和内部拦截。

一、外部拦截:重写父容器的onInterceptTouchEvent方法
我们要求在滑动的时候才让子控件拦截点击事件,也就是,在按下和抬起的时候子控件拦截,于是,我们的代码可以这样写:

@Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        boolean isIntercept = false;
        int action = e.getAction();
        int currentX = (int) e.getX();
        int currentY = (int) e.getY();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                isIntercept = false;//点击事件分发给子控件
                break;
            case MotionEvent.ACTION_MOVE:
                if(isParentIntercept(currentX,currentY,lastX,lastY)){//父容器拦截
                    isIntercept = true;
                }else {//点击事件分发给子控件
                    isIntercept = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                isIntercept = false;//点击事件分发给子控件
                break;
        }
        //记录上次滑动的位置
        lastX = currentX;
        lastY = currentY;
        return isIntercept;
    }

二、内部拦截:重写子控件的dispatchTouchEvent方法,配合父容器对象调用requestDisallowInterceptToucEvent方法来实现点击事件的拦截,于是代码可以这样写:

    @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);//父容器不拦截点击事件,子控件拦截点击事件
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - lastX;
                int deltaY = y - lastY;
                if(Math.abs(deltaY) - Math.abs(deltaX) > 0){//竖直滑动的父容器拦截事件
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        lastX = x;
        lastY = y;
        return super.dispatchTouchEvent(ev);
    }

好了,两种拦截方法就介绍完了,大家可以根据相应的情况选择合适拦截方法。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐