1、设置布局:
RecyclerView的Item的布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="60dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
card_view:cardCornerRadius="8dp">
<TextView
android:id="@+id/tv_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="A"
android:textColor="#4DB6AC"
android:textSize="10sp" />
</android.support.v7.widget.CardView>
</RelativeLayout>
RecyclerView的Foot布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/progressbar_refresh" />
<TextView
android:id="@+id/tv_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:text="正在加载..."
android:textColor="#4DB6AC"
android:textSize="16sp" />
<LinearLayout
android:id="@+id/ll_end"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:alpha="0.5"
android:background="#4DB6AC"
android:gravity="start" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="大哥已经没有更多的数据"
android:textColor="#4DB6AC"
android:textSize="16sp" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:alpha="0.5"
android:background="#4DB6AC"
android:gravity="end" />
</LinearLayout>
</LinearLayout>
/**
* Created by csc on 2018/4/3.
* explain:主要实现的是分布局(正常的内容和Foot)
*/
public class LoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//实体数据
private List<String> mList;
//普通布局
private final int TYPE_ITEM=0;
//脚布局
private final int TYPE_FOOTER=1;
//当前加载状态,默认为加载完成
private int loadState=2;
//正在加载
public final int LOADING=1;
//加载完成
public final int LOADING_COMPLIETE=2;
//加载到底
public final int LOADING_END=3;
//构造器赋值
public LoadMoreAdapter(List<String> list) {
mList = list;
}
@Override
public int getItemViewType(int position) {
if(position+1 == getItemCount() ){
//最后一个Item显示脚布局
return TYPE_FOOTER;
}else{
//返回正常的条目
return TYPE_ITEM;
}
}
//设置布局
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM){
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_recyclerview,parent,false);
return new RecyclerViewHolder(view);
}else if (viewType == TYPE_FOOTER){
View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_refresh_footer,parent,false);
return new FooterViewHolder(view);
}
return null;
}
//绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof RecyclerViewHolder){
RecyclerViewHolder itemHolder= (RecyclerViewHolder) holder;
itemHolder.tvItem.setText(mList.get(position));
}else if (holder instanceof FooterViewHolder){
final FooterViewHolder footerViewHolder= (FooterViewHolder) holder;
switch (loadState){
//正在加载
case LOADING:
footerViewHolder.pbLoading.setVisibility(View.VISIBLE);
footerViewHolder.tvLoading.setVisibility(View.VISIBLE);
//设置加载完成布局为隐藏
footerViewHolder.llEnd.setVisibility(View.GONE);
break;
//加载完成
case LOADING_COMPLIETE:
footerViewHolder.pbLoading.setVisibility(View.INVISIBLE);
footerViewHolder.tvLoading.setVisibility(View.INVISIBLE);
footerViewHolder.llEnd.setVisibility(View.GONE);
break;
//加载所有的条目完成
case LOADING_END:
footerViewHolder.pbLoading.setVisibility(View.GONE);
footerViewHolder.tvLoading.setVisibility(View.GONE);
footerViewHolder.llEnd.setVisibility(View.VISIBLE);
/* new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//1秒以后吧没有更多数据提示隐藏
footerViewHolder.llEnd.setVisibility(View.GONE);
}
},1000);*/
break;
default:
break;
}
}
}
//提供一个方法判断:上来加载的状态
//0:正在加载 1:加载完成 2:已经没有更多的数据
public void setLoadState(int loadState){
this.loadState=loadState;
notifyDataSetChanged();
}
//正常条目的布局类
private class RecyclerViewHolder extends RecyclerView.ViewHolder{
private TextView tvItem;
public RecyclerViewHolder(View itemView) {
super(itemView);
tvItem=itemView.findViewById(R.id.tv_item);
}
}
//脚布局
private class FooterViewHolder extends RecyclerView.ViewHolder{
private ProgressBar pbLoading;
private TextView tvLoading;
private LinearLayout llEnd;
public FooterViewHolder(View itemView) {
super(itemView);
pbLoading=itemView.findViewById(R.id.pb_loading);
tvLoading=itemView.findViewById(R.id.tv_loading);
llEnd=itemView.findViewById(R.id.ll_end);
}
}
//总的条目数量
@Override
public int getItemCount() {
//加上脚布局,所以+1
return mList.size()+1;
}
//当网格布局的时候应该是foot居中显示,而不是显示在左边的位置
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager=recyclerView.getLayoutManager();
//判断是网格布局
if (manager instanceof GridLayoutManager){
final GridLayoutManager gridLayoutManager= (GridLayoutManager) manager;
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//如果当前是footer的位置
//这个footer占据1个单元格
return getItemViewType(position) == TYPE_FOOTER?gridLayoutManager.getSpanCount():1;
}
});
}
}
}
/**
* Created by csc on 2018/4/3.
* explain:在Adapter中设置好FooterView之后,我们需要判断一下什么时候显示出来,
* 这时就需要对RecyclerView设置一下滑动监听,当滑动到最后一条Item的时候,显示加载更多UI(Footer)
* 并且开始请求下一个列表数据
*/
abstract class EndLessRecyclerOnScrollListener extends RecyclerView.OnScrollListener{
//用来记录是否正在向上滑动
private boolean isSlidingUpward=false;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
LinearLayoutManager manager= (LinearLayoutManager) recyclerView.getLayoutManager();
//当前不滑动时
if(newState == RecyclerView.SCROLL_STATE_IDLE){
//获取到最后一个完全显示的ItemPosition
int lastItemPosition=manager.findLastCompletelyVisibleItemPosition();
//现在总条目数
int itemCount=manager.getItemCount();
//判断是否滑动到了最后一个Item,并且向上滑动
if (lastItemPosition == (itemCount -1) && isSlidingUpward){
//加载更多
onLoadMore();
}
}
}
//判断RecyclerView是否是向上滑动
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//大于0表示正在向上滑动,小于0表示停止或向下滑动
isSlidingUpward =dy>0;
}
//加载更多的数据回调
public abstract void onLoadMore();
}
5、设置适配器和监听:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRv;
private LoadMoreAdapter mAdapter;
//假数据
private List<String> mList;
//数据的总页数
private int totalPage=5;
//当前加载的页数
private int currentPage=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRv = (RecyclerView) findViewById(R.id.rv);
initView();
initData();
initAdapter();
}
private void initView() {
mRv.setLayoutManager(new LinearLayoutManager(this));
}
private void initData() {
//设置一些假数据
mList=new ArrayList<>();
for (int i = 0; i < 10; i++) {
mList.add("我是假数据"+1);
}
}
private void initAdapter() {
mAdapter=new LoadMoreAdapter(mList);
mRv.setAdapter(mAdapter);
//给RecyclerView设置加载更多监听
mRv.addOnScrollListener(new EndLessRecyclerOnScrollListener() {
@Override
public void onLoadMore() {
/***************显示正在加载数据的footer****************/
mAdapter.setLoadState(mAdapter.LOADING);
//判断加载的页数 等于 总的页数
if (totalPage == currentPage){
/***********************表示数据加载完成************************/
mAdapter.setLoadState(mAdapter.LOADING_END);
}else{
//表示去加载更多的数据
//模拟一个耗时操作
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
getMoreData();
/*******************隐藏显示正在加载条目的Footer布局UI************/
mAdapter.setLoadState(mAdapter.LOADING_COMPLIETE);
}
});
}
},2000);
}
}
});
}
//设置一个添加假数据
public void getMoreData(){
currentPage++;
for (int i = 0; i < 5; i++) {
mList.add("我是加载更多的数据:"+i+",当前的页数是:"+currentPage);
}
}
}
6、运行结果
7、进行封装
public class LoadMoreWrapper extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//普通的布局
private final int TYPE_ITEM=0;
//脚布局
private final int TYPE_FOOTER=1;
//当前加载状态,默认为加载完成
private int loadState=2;
//正在加载
public final int LOADING=1;
//加载完成
public final int LOADING_COMPLETE=2;
//加载到底
public final int LOADING_END=3;
//适配器
private RecyclerView.Adapter mAdapter;
public LoadMoreWrapper(RecyclerView.Adapter adapter) {
mAdapter = adapter;
}
//分布局
@Override
public int getItemViewType(int position) {
if (position+1 == getItemCount()){
return TYPE_FOOTER;
}else{
return TYPE_ITEM;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//进行判断显示类型,来创建还回不同的View
if (viewType == TYPE_FOOTER){
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_refresh_footer,parent,false);
//还回的是脚布局
return new FootViewHolder(view);
}else{
//还回的是内容的布局
return mAdapter.onCreateViewHolder(parent,viewType);
}
}
//绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof FootViewHolder){
FootViewHolder footViewHolder= (FootViewHolder) holder;
switch (loadState){
//表示正在加载
case LOADING:
footViewHolder.pbLoading.setVisibility(View.VISIBLE);
footViewHolder.tvLoading.setVisibility(View.VISIBLE);
footViewHolder.llEnd.setVisibility(View.GONE);
break;
//表示加载完成
case LOADING_COMPLETE:
footViewHolder.pbLoading.setVisibility(View.INVISIBLE);
footViewHolder.tvLoading.setVisibility(View.INVISIBLE);
footViewHolder.llEnd.setVisibility(View.GONE);
break;
//表示加载到底
case LOADING_END:
footViewHolder.pbLoading.setVisibility(View.GONE);
footViewHolder.tvLoading.setVisibility(View.GONE);
footViewHolder.llEnd.setVisibility(View.VISIBLE);
break;
default:
break;
}
}else{
mAdapter.onBindViewHolder(holder,position);
}
}
//总的条目数量
@Override
public int getItemCount() {
return mAdapter.getItemCount()+1;
}
//脚布局
private class FootViewHolder extends RecyclerView.ViewHolder{
ProgressBar pbLoading;
TextView tvLoading;
LinearLayout llEnd;
public FootViewHolder(View itemView) {
super(itemView);
pbLoading=itemView.findViewById(R.id.pb_loading);
tvLoading=itemView.findViewById(R.id.tv_loading);
llEnd=itemView.findViewById(R.id.ll_end);
}
}
//当时网格布局的时候Foot需要居中显示
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager=recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager){
final GridLayoutManager gridLayoutManager= (GridLayoutManager) manager;
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//如果是脚布局据合并单元格
return getItemViewType(position)==TYPE_FOOTER?1:gridLayoutManager.getSpanCount();
}
});
}
}
//设置上拉的时候改变对应的状态
public void setLoadState(int loadState){
this.loadState=loadState;
notifyDataSetChanged();
}
}
我们乍一眼看和上面的LoadMoreAdapter没有什么区别,都是继承了RecyclerView.Adapter并且实现了其中的一些方法,但是我们仔细看会发现,构造器中的参数变成了RecyclerView.Adapter,在LoadMoreWrapper中我们只处理加载更多功能相关的逻辑,其他逻辑都交给Adapter本身去处理,相当于扩展了Adapter的一些功能,这种方式还有一个学名叫【装饰者模式】
封装以后的Rv的Adapter变成这样:
public class LoadMoreWrapperAdaoter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
//数据
private List<String> mList;
public LoadMoreWrapperAdaoter(List<String> list) {
this.mList = list;
}
//加载内容布局
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_recyclerview,parent,false);
RecyclerViewHolder recyclerViewHolder=new RecyclerViewHolder(view);
return recyclerViewHolder;
}
//绑定内容的数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
RecyclerViewHolder recyclerViewHolder= (RecyclerViewHolder) holder;
System.out.println("当前的条目数据为:"+mList.get(position));
recyclerViewHolder.tvItem.setText(mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
//Adapter的内容布局
private class RecyclerViewHolder extends RecyclerView.ViewHolder{
TextView tvItem;
public RecyclerViewHolder(View itemView) {
super(itemView);
tvItem=itemView.findViewById(R.id.tv_item);
}
}
}
然后就是给RecyclerView设置适配器:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRv;
//假数据
private List<String> mList;
//数据的总页数
private int totalPage = 5;
//当前加载的页数
private int currentPage = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRv = (RecyclerView) findViewById(R.id.rv);
initView();
initData();
initAdapter();
}
private void initView() {
mRv.setLayoutManager(new LinearLayoutManager(this));
}
private void initData() {
//设置一些假数据
mList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
mList.add("我是假数据" + 1);
}
}
LoadMoreWrapper mAdapter;
private void initAdapter() {
/*******************主要的改变*********************/
//就是在原有Adapter的基础上包上一层
LoadMoreWrapperAdaoter loadMoreWraooerAdaoter = new LoadMoreWrapperAdaoter(mList);
mAdapter = new LoadMoreWrapper(loadMoreWraooerAdaoter);
mRv.setAdapter(mAdapter);
//给RecyclerView设置加载更多监听
mRv.addOnScrollListener(new EndLessRecyclerOnScrollListener() {
@Override
public void onLoadMore() {
/***************显示正在加载数据的footer****************/
mAdapter.setLoadState(mAdapter.LOADING);
//判断加载的页数 等于 总的页数
if (totalPage == currentPage) {
/***********************表示数据加载完成************************/
mAdapter.setLoadState(mAdapter.LOADING_END);
} else {
//表示去加载更多的数据
//模拟一个耗时操作
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
getMoreData();
/*******************隐藏显示正在加载条目的Footer布局UI************/
mAdapter.setLoadState(mAdapter.LOADING_COMPLETE);
}
});
}
}, 2000);
}
}
});
}
//设置一个添加假数据
public void getMoreData() {
currentPage++;
for (int i = 0; i < 5; i++) {
mList.add("我是加载更多的数据:" + i + ",当前的页数是:" + currentPage);
}
}
}