Android---SwipeRefreshLayout嵌套ViewPager时的滑动冲突

版权声明:转载请标明出处: https://blog.csdn.net/Sunny_Captain/article/details/82966386

SwipeRefreshLayout嵌套ViewPager

最近在项目中用到了SwipeRefreshLayout控件,以实现下拉刷新,在我的SwipeRefreshLayout布局中存在一个ViewPager。那么问题就出现了,当我对ViewPager进行左右滑动时,只要你的滑动手势有偏下,即往左下或者右下滑动时,会触发SwipeRefreshLayout的下拉动作,导致不能正常对ViewPager进行滑动操作。

解决方法

对于Android的事件分发机制在这篇文章里就不再赘述,之后有时间再写篇文章针对事件分发进行阐述吧。那对于本文描述的这种情况,其实思路很简单,即对用户的滑动手势进行判断,下拉事件就交给SwipeRefreshLayout处理,左右滑动事件SwipeRefreshLayout就不进行拦截,直接下发到ViewPager进行处理。那怎么区分下拉还是左右滑动呢,我用到的一个思路就是根据用户移动手势的X方向位移dx和Y方向位移dy进行判断,如果dx>dy,那么就认为是左右滑动,交给ViewPager,如果dy>dx,就认为是上下滑动,交给SwipeRefreshLayout并拦截(看源码你会发现SwipeRefreshLayout是继承ViewGroup的,对事件进行拦截后就不会再下发到子View,具体流程在此不赘述)。

代码示例

下面的代码是我重写的一个SwipeRefreshLayout,对用户滑动手势进行了判断处理:

public class SunnySwipeRefreshLayout extends SwipeRefreshLayout {
    private float startX;
    private float startY;
    private boolean mIsXMove;// 是否横向拖拽
    private final int mTouchSlop;// getScaledTouchSlop()得来的一个距离,表示滑动的时候,手势移动要大于这个距离才开始移动控件,ViewPager就是用这个距离来判断用户是否翻页

    public SunnySwipeRefreshLayout (Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            mIsXMove = false;
            startX = ev.getX();
            startY = ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            // 如果横向移动则不拦截,直接return false;
            if (mIsXMove) {
                return false;
            }
            float endX = ev.getX();
            float endY = ev.getY();
            float distanceX = Math.abs(endX - startX);
            float distanceY = Math.abs(endY - startY);
            // 如果dx>xy,则认定为左右滑动,将事件交给viewPager处理,return false
            if (distanceX > mTouchSlop && distanceX > distanceY) {
                mIsXMove= true;
                return false;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            mIsXMove= false;
            break;
        }
        // 如果dy>dx,则认定为下拉事件,交给swipeRefreshLayout处理并拦截
        return super.onInterceptTouchEvent(ev);
    }
}

这么处理之后,在这个下拉刷新布局中再嵌套ViewPager或是其他存在左后滑动操作的控件时,就不会再产生这种滑动冲突啦。
大家如果有更好的方案欢迎留言讨论~

没有更多推荐了,返回首页