有关RecyclerView的类似SwipeRefreshLayout的上拉加载更多,我写了一篇博客http://blog.csdn.net/cj_286/article/details/52767070
但是之前写的那个有一点点的小问题,如果上拉刷新,刷新小图标还没有移动到刷新位置,刷新数据就已经获取到,并且调用了setRefreshing(false),在setRefreshing(false)中会去调用translationTo(int from,int to,final boolean isShow),将刷新图标隐藏,而在上拉刷新的时候,也会去调用translationTo(int from,int to,final boolean isShow),将图标移动到刷新位置,就在移动过程中还没有结束,就调用了停止刷新,这样就会出现问题,所以解决办法就是如果在上拉加载更多的时候,如果刷新图标还没有移动到刷新位置就调用了setRefreshing(false)来停止刷新,这是就要等待让其移动到指定位置之后再停止,所以就需要提供一个借口监听,上拉刷新图标到指定位置回调该接口,在setRefreshing(false)中如果上拉刷新图标还在移动过程中就设置监听,在监听回调中再去停止刷新,这样就解决了以上的bug.translationTo(int from,int to,final boolean isShow)方法修改后的代码如下:
/**
* 执行平移动画
* @param from
* @param to
*/
private void translationTo(int from,int to,final boolean isShow){
//1.调用ofInt(int...values)方法创建ValueAnimator对象
ValueAnimator mAnimator = ValueAnimator.ofInt(from,to);
//2.为目标对象的属性变化设置监听器
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 3.为目标对象的属性设置计算好的属性值
int animatorValue = (int)animation.getAnimatedValue();
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mImageView.getLayoutParams();
marginLayoutParams.bottomMargin = animatorValue;
mImageView.setLayoutParams(marginLayoutParams);
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if(isShow){
start();
mPrepareAnimation = false;
//设置准备刷新的回调,防止在没有到刷新的位置,就已经调用了setRefreshing(false)来停止刷新,这样就会出现问题
//内部使用
if(mPrepareAnimationListener != null){
mPrepareAnimationListener.finishAnimation();
}
}else{
hideRefreshArrow();
hide();
}
}
});
//4.设置动画的持续时间、是否重复及重复次数等属性
mAnimator.setDuration(100);
//mAnimator.setRepeatCount(3);
mAnimator.setRepeatMode(ValueAnimator.INFINITE);
//5.为ValueAnimator设置目标对象并开始执行动画
mAnimator.setTarget(mImageView);
mAnimator.start();
}
监听接口定义
/**
* 准备刷新动画的监听,就是上拉后,移动到刷新位置的监听
*/
interface PrepareAnimationListener{
void finishAnimation();
}
private PrepareAnimationListener mPrepareAnimationListener;
private void setPrepareAnimationListener(PrepareAnimationListener listener){
mPrepareAnimationListener = listener;
}
setRefreshing(boolean refreshing)代码修改后如下:
/**
* 加载更多或停止加载更多
* @param refreshing
*/
public void setRefreshing(boolean refreshing) {
if(!mIsAllowLoadMore) return;
if(refreshing){
if(mStart) return;
showRefreshArrow();
getValueToTranslation();
mPrepareAnimation = true;
mIsRefreshing = true;//正在刷新
if (mOnPullListener != null) {
mOnPullListener.onLoadMore(this);
}
mIsCanScoll = false;
}else {
//如果准备执行动画(平移到刷新转圈的位置)结束后才能停止
if(!mPrepareAnimation) {
setRefreshStop();
}else{
//上拉加载的View还没有到刷新转圈的地方,就停止了刷新,所以要设置准备刷新的监听,
//等到刷新的地方了,再调用停止刷新
setPrepareAnimationListener(new PrepareAnimationListener() {
@Override
public void finishAnimation() {
setRefreshStop();
}
});
}
}
}
/**
* 获取底部可见项的位置
* 获取最后一个条目的索引
* @param lastPos 如果是瀑布流的话就返回每一列最后一个条目的索引
* @return
*/
private int getLastVisibleItemPosition(int[] lastPos) {
RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
int lastVisibleItemPosition = 0;
if (lm instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) lm).findLastVisibleItemPosition();
} else if (lm instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) lm).findLastVisibleItemPosition();
}else if(lm instanceof StaggeredGridLayoutManager){
StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager)lm;
int columnCount = layoutManager.getColumnCountForAccessibility(null, null);//获取瀑布流的列数
//int columnCount = layoutManager.getSpanCount();//获取瀑布流的列数
int[] positions = new int[columnCount];
layoutManager.findLastVisibleItemPositions(positions);//获取瀑布流的每一列的最下面的条目的索引(并不是最后n个(n为瀑布流的列数)),有的条目可能会很长
lastVisibleItemPosition = getArrayMax(positions);//返回其中最大的一个(它是乱序的,并不是按顺序保存的)
System.arraycopy(positions,0,lastPos,0,positions.length);
//瀑布流的布局方式是哪一列的高度最小,下一个条目就排到哪一列的后面
}
return lastVisibleItemPosition;
}
瀑布流是否已经到底部了
/**
* 判断最后几个有一个到底部了就说明到底部了
* @param layoutManagers
* @param lastPos
* @return
*/
private boolean staggeredCanPullUp(RecyclerView.LayoutManager layoutManagers, int[] lastPos){
if(!(layoutManagers instanceof StaggeredGridLayoutManager)) return false;
int bottom = 0;
for(int i=0;i bottom) {
bottom = layoutManagers.findViewByPosition(lastPos[i]).getBottom();
}
}
//return false;
return bottom <= getHeight();
}
好了,暂时我就发现这两点问题,如果还有其他的问题或是不合理的地方,欢迎留言
在该Demo中的RecyclerView的万能设配器是CSDN鸿洋博客中的http://blog.csdn.net/lmj623565791/article/details/51118836
下载地址:CSDN