banner是一个第三方轮播库,到现在为止已经有8000+的star了,使用的人也很多。使用的人越多,业务场景就越多,相应的问题也会越多。比如SwipeRefreshLayout嵌套banner的时候,就会使banner手动滑动起来特别的费劲,经常滑不过去。
https://github.com/youth5201314/banner
思路:
- 因为下拉刷新,只有纵向滑动的时候才有效,只需要判断此时是纵向滑动还是横向滑动就可以了。
- 纵向滑动就拦截事件,横向滑动不拦截。
- 怎么判断是纵向滑动还是横向滑动,只要判断Y轴的移动距离大于X轴的移动距离那么就判定为纵向滑动就行了。
自定义SwipeRefreshLayout
/** * Created by yechaoa on 2019/06/25. * Describe : 重写SwipeRefreshLayout的onIntercept方法解决与viewpager冲突问题。 * 思路: * 1. 因为下拉刷新,只有纵向滑动的时候才有效,只需要判断此时是纵向滑动还是横向滑动就可以了。 * 2. 纵向滑动就拦截事件,横向滑动不拦截。 * 3. 怎么判断是纵向滑动还是横向滑动,只要判断Y轴的移动距离大于X轴的移动距离那么就判定为纵向滑动就行了。 */ public class SuperSwipeRefreshLayout extends SwipeRefreshLayout { private float startY; private float startX; // 记录viewPager是否拖拽的标记 private boolean mIsVpDragger; private final int mTouchSlop; public SuperSwipeRefreshLayout(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: // 记录手指按下的位置 startY = ev.getY(); startX = ev.getX(); // 初始化标记 mIsVpDragger = false; break; case MotionEvent.ACTION_MOVE: // 如果viewpager正在拖拽中,那么不拦截它的事件,直接return false; if (mIsVpDragger) { return false; } // 获取当前手指位置 float endY = ev.getY(); float endX = ev.getX(); float distanceX = Math.abs(endX - startX); float distanceY = Math.abs(endY - startY); // 如果X轴位移大于Y轴位移,那么将事件交给viewPager处理。 if (distanceX > mTouchSlop && distanceX > distanceY) { mIsVpDragger = true; return false; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 初始化标记 mIsVpDragger = false; break; } // 如果是Y轴位移大于X轴,事件交给swipeRefreshLayout处理。 return super.onInterceptTouchEvent(ev); } }
而后把原来的SwipeRefreshLayout 换成SuperSwipeRefreshLayout 即可。
扩展:
SwipeRefreshLayout 嵌套 RecyclerView滑动冲突
SwipeRefreshLayout 嵌套ScrollView 滑动冲突