下拉刷新,滑动到底部加载更多是App中很常见的功能,github上也有很多这样的开源库提供这样的功能,但大多数是在listview,recycleview等列表类上面做了一层包装,后来google推出了官方的刷新组件SwipeRefreshLayout,SwipeRefreshLayout是Android开发功常用的一个组件,使用起来很方便,但是没有加载更多这个功能,是否可以对SwipeRefreshLayout做些改动,使其能够支持加载更多呢,答案是肯定的。
首先对SwipeRefreshLayout进行分析:
public class SwipeRefreshLayout extends ViewGroup implements NestedScrollingParent,
NestedScrollingChild
- 可以看到SwipeRefreshLayout实现了NestedScrollingParent,NestedScrollingChild这两个接口,这两个接口是实现组件之间协同滑动的重要接口,使用也不麻烦主要用到NestedScrollingParentHelper ,NestedScrollingChildHelper这两个帮助类。
- 对于不支持NestedScrolling的view SwipeRefreshLayout采用拦截滑动事件,判断是否需要刷新。
-
刷新的动画则是一个圆形的ImageView加一个圆形的progressDrawable,通过一系列的Animation完成的,这部分代码可以拷贝出来直接使用。
有了大概思路之后就可以开始写代码了
- 新建类继承ViewGroup,并实现NestScrollingParent,NestScrollingChild
- 在NestScrollingParent和onInterceptTouchEvent中对用户的手势操作做判断。
- refresh,loadmore的显示与消失的处理
- 数据全部加载完成,没有更多时的显示
遇到的问题及解决办法
fling时滑动到底部loadmore的显示
因为之前对view的滑动没有太了解,所以在判断SwipeRefrshPlush中的子view是否滑动到底部时不知道该如何下手,最后还是贼SwipeRefreshLayout的源码中找到了解决方法
public boolean canChildScrollDown() {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
int count = absListView.getChildCount();
int position = absListView.getLastVisiblePosition();
return (count > position + 1) || absListView.getChildAt(position).getBottom() <=absListView.getPaddingBottom();
} else {
return ViewCompat.canScrollVertically(mTarget, 1);
}
} else {
return ViewCompat.canScrollVertically(mTarget, 1);
}
}
refresh或loadmore动画正在显示时fragment切换导致重叠
这个问题在SwipeRefreshLayout中也存在,不过以前一直没发现,导致这个问题出现的原因是ProgressDrawable中使用的是Animation动画,后来将ProgressDrawable中的动画改为Animator动画,这个问题就得到了解决。