- 为什么要自定义view来实现recylcerview的上拉加载,就为了方便复用,只要写好一次,之后只将要写的类拷贝到新的项目中就能直接使用.不过在xml中必须使用你定义的View,下面直接上代码
/**
* 具有上拉加载的recylcerview,默认是没有上拉加载的功能,只有当可见item超过屏幕才会出现上拉加载
* Created by lyf
*/
public class MyRecyclerView extends RecyclerView {
private boolean isLoadingMore = false; // 是否正在加载更多中, 默认为: false
private OnRefreshLoadListener listener; //回调接口
private boolean isUp;//是否是向上滑动
public MyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initFooter(context);
}
public MyRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
initFooter(context);
}
public MyRecyclerView(Context context) {
this(context, null);
}
/**
* 初始化
*/
public void initFooter(Context context) {
this.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
LinearLayoutManager linearLayoutManager1 = (LinearLayoutManager) layoutManager;
//获取最后一个可见条目的位置
int lastVisibleItem = linearLayoutManager1.findLastVisibleItemPosition();
//获取第一个可见条目的位置
int first = linearLayoutManager1.findFirstVisibleItemPosition();
//屏幕中可见的item个数
int visbleItemCount = lastVisibleItem - first;
//获取总的条目数
int totalItemCount = recyclerView.getAdapter().getItemCount();
//如果可见的条目小于总的条目数,表示数据超过了屏幕,就显示更多加载,才执行loadMore
if(visbleItemCount <totalItemCount - 1 ){
listener.show(true);
//等滑倒最后,必须是向上滑动且停止滑动了在加载
if (newState == RecyclerView.SCROLL_STATE_IDLE
&& lastVisibleItem + 1 == totalItemCount && isUp) {
//如果没有正在加载中,就执行加载的方法
if (!isLoadingMore) {
isLoadingMore = true;
//回调方法,写你自己加载的逻辑
listener.loadMore();
}
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//dy>0 表示向上滑动
if (dy > 0) {
isUp = true;
}else{
isUp = false;
}
}
});
}
/**
* 设置是否正在加载
* @param isLoadingMore
*/
public void setIsLoadingMore(boolean isLoadingMore) {
this.isLoadingMore = isLoadingMore;
}
/**
* 设置接口
* @param listener
*/
public void setOnRefreshLoadListener(OnRefreshLoadListener listener) {
this.listener = listener;
}
/**
* 回调的接口
*/
interface OnRefreshLoadListener {
/**
* 加载更多
*/
public void loadMore();
/**
* 是否显示最后一个条目
* @param isShow
*/
public void show(boolean isShow);
}
}
含有加载更多布局的适配器
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Integer> datas;
private Context context;
//加载的几种状态
private static final int STATE = 0; //默认状态
private static final int ERROR = 1; //加载失败
private static final int EMPTY = 2; //加载成功,但数据为空
private int loading; //加载的状态
private boolean isShow;//是否显示加载更多
//几种类型的条目
private static final int TYPE_ITEM = 0;
private static final int TYPE_FOOTER = 1;
public MyRecyclerViewAdapter(Context context, List<Integer> datas) {
this.datas = datas;
this.context = context;
}
@Override
public int getItemViewType(int position) {
// 最后一个item设置为footerView ,主要是调用的getItemCount
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
/**
* 创建view调用的方法
* @param parent
* @param viewType view的类型
* @return
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) { //如果是条目
View view = LayoutInflater.from(context).inflate(R.layout.layout_item, parent, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
} else if (viewType == TYPE_FOOTER) {//如果是最后一个条目
//必须用这个加载view 否则会不对
View view = LayoutInflater.from(context).inflate(R.layout.refresh_footer_view, parent, false);
LoadHolder loadHolder = new LoadHolder(view);
return loadHolder;
}
return null;
}
/**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyViewHolder) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
myViewHolder.mTextView.setText(position + "");
} else if (holder instanceof LoadHolder) {
LoadHolder loadHolder = (LoadHolder) holder;
//默认更多加载不显示
if (isShow){
loadHolder.ll_refresh.setVisibility(View.VISIBLE);
}else{
loadHolder.ll_refresh.setVisibility(View.GONE);
}
switch (loading) {
case STATE:
loadHolder.progressBar.setVisibility(View.VISIBLE);
loadHolder.title.setText("加载中,请稍后...");
break;
case ERROR:
loadHolder.progressBar.setVisibility(View.GONE);
loadHolder.title.setText("加载失败");
break;
case EMPTY:
loadHolder.progressBar.setVisibility(View.GONE);
loadHolder.title.setText("没有更多数据");
break;
}
}
}
@Override
public int getItemCount() {
return datas.size() + 1;
}
public void setIsShow(boolean isShow) {
this.isShow = isShow;
}
/**
* 设置加载的状态
*
* @param loading
*/
public void setLoading(int loading) {
this.loading = loading;
}
}
/**
* 正常条目的holder
*/
class MyViewHolder extends RecyclerView.ViewHolder {
TextView mTextView;
public MyViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.item_tv);
}
}
/**
* 加载更多的view
*/
class LoadHolder extends RecyclerView.ViewHolder {
TextView title;
ProgressBar progressBar;
LinearLayout ll_refresh; //加载更多的布局
public LoadHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.tv_refresh_footer);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar);
ll_refresh = (LinearLayout) itemView.findViewById(R.id.ll_refresh);
}
}
下面是加载更多的xml布局:
<<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/ll_refresh"
android:layout_height="48dp"
android:background="#fff"
android:gravity="center"
android:visibility="gone"
android:orientation="horizontal" >
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:indeterminateDrawable="@drawable/custom_progressbar" />
<TextView
android:id="@+id/tv_refresh_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:text="加载中,请稍后"
android:textColor="#cccccc"
android:textSize="15sp" />
</LinearLayout>
java代码:
mRecyclerView = (MyRecyclerView) this.findViewById(R.id.recyclerView);
datas = new ArrayList<>();
linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
//给recyclerview设置item增加,删除动画效果
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
for (int i = 0; i < 10; i++) {
datas.add(i);
}
adapter = new MyRecyclerViewAdapter(this, datas);
mRecyclerView.setAdapter(adapter);
//设置加载更多
mRecyclerView.setOnRefreshLoadListener(this);
/**
* 加载更多的回调方法
*/
public void loadMore() {
在这里写你上拉加载的逻辑,只是当你加载完成以后需要调用下面的代码 ,还有就是可以在这里通过adapter.setLoading(0)方法来设置加载的状态,0表示加载成功,1表示加载失败,2表示加载成功,但是数据为空
//设置加载完了
mRecyclerView.setIsLoadingMore(false);
}
/**
* 是否显示更多加载的回调方法
* @param isShow
*/
@Override
public void show(boolean isShow) {
当isShow为true时,表示recylcerview的条目超过屏幕,可以显示加载更多的布局,在适配器中默认是不显示加载更多的布局的,可以通过下面的代码让它显示.
adapter.setIsShow(isShow);
//刷新加载更多这一个条目
adapter.notifyItemRangeChanged(0,adapter.getItemCount());
}
2.只要将上面3个类创建好就可以实现recylcerview的上拉加载效果,且如果recylcerview的条目个数没有超过屏幕时,上拉加载的布局就不会显示,上拉加载的功能也不能使用.且可以在loadmore回调方法中根据服务器返回的状态来设置加载更多的状态.