關于RecycleView實作上拉加載更多的思路和方法,我相信每個人都有那麼幾套,
比如我
1、使用的是 BaseRecycleViewAdapterHelper 因為這個庫真的幫助我們實作了好多的東西,結合Rxjava+Retrofit在項目中的使用,在不同的狀态進行處理不同的業務邏輯,是以這個Adapter已經完完全全的實作了。
2、最開始選擇這個庫的原因是:裡面可以通過幾句代碼實作item滑動的動畫,也可以很友善的自定義動畫。
3、比一般的更穩定,因為上拉會産生很多的問題,或者多滑幾次會出現卡頓,不加載等問題。
好了,說了很多的廢話,開始我們正題。
GitHub傳送門 https://github.com/OnexZgj/OneX (包含很多的測試代碼,選擇RecycleView LoadMore)Button 進行檢視效果
先看看一下Demo運作的效果(沒有多布局)

RecycleView增加HeadView和FooterView 的Demo(由于轉換的gif失真)
多布局界面的顯示
上拉加載更多的界面截圖
正在重新整理的界面截圖
看到網上很多的Adapter的架構,我們也自己實作一個Adapter
一、先實作LoadMoreAdapter(實作RecycleViewAdapter的最基本的方式)
/**
* Created by zgj on 2017/11/6:10:37.
* des: 上拉加載更多的adapter
*/
public class LoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> dataList;
// 普通布局
private final int TYPE_ITEM = 1;
// 腳布局
private final int TYPE_FOOTER = 2;
// 目前加載狀态,預設為加載完成
private int loadState = 2;
// 正在加載
public final int LOADING = 1;
// 加載完成
public final int LOADING_COMPLETE = 2;
// 加載到底
public final int LOADING_END = 3;
public LoadMoreAdapter(List<String> dataList) {
this.dataList = dataList;
}
@Override
public int getItemCount() {
//資料加1
return dataList.size()+1;
}
@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) {
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 FootViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//正常布局的holder
if (holder instanceof RecyclerViewHolder){
RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;
recyclerViewHolder.tvItem.setText(dataList.get(position));
}else if (holder instanceof FootViewHolder){
FootViewHolder footViewHolder = (FootViewHolder) holder;
}
}
}
二、ViewHolder 的實作
/**
* 正常條目的item的ViewHolder
*/
private class RecyclerViewItemHolder extends RecyclerView.ViewHolder {
TextView tvItem;
RecyclerViewItemHolder(View itemView) {
super(itemView);
tvItem = (TextView) itemView.findViewById(R.id.tv_item);
}
}
/**
* FootView的Holder
*/
private class FootViewHolder extends RecyclerView.ViewHolder {
/**
* 進度條展示
*/
ProgressBar pbLoading;
/**
* 正在加載的TextView
*/
TextView tvLoading;
/**
* 伺服器沒有資料資訊展示
*/
LinearLayout llEnd;
/**
* 進行提示的布局資訊
*/
LinearLayout llWarn;
FootViewHolder(View itemView) {
super(itemView);
pbLoading = (ProgressBar) itemView.findViewById(R.id.pb_loading);
tvLoading = (TextView) itemView.findViewById(R.id.tv_loading);
llEnd = (LinearLayout) itemView.findViewById(R.id.ll_end);
llWarn = (LinearLayout) itemView.findViewById(R.id.ll_warn);
}
}
因為我們要通過判斷滑動的狀态,去控制FootView的顯示和隐藏,是以設定成員方法SetLoadState(); 來接受滑動的狀态的改變
public void setLoadState(int loadState) {
this.loadState = loadState;
notifyDataSetChanged();
}
三、在Adapter中的事情大體已經完成了,接下來實作,如何進行判斷目前recycleView的滑動的狀态和資料的加載的狀态
package com.example.linsa.retrofitdemo.listener;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
/**
* Created by zgj on 2017/11/6:11:09.
* des:
*/
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
/**
* 标記是否正在向上滑動
*/
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) {
//當狀态是不滑動的時候
int lastItemPosition = manager.findLastCompletelyVisibleItemPosition();
int itemCount = manager.getItemCount();
if (lastItemPosition == (itemCount - 1) && isSlidingUpward) {
onLoadMoreData();
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// 大于0表示正在向上滑動,小于等于0表示停止或向下滑動
isSlidingUpward = dy > 0;
}
/**
* 加載更多資料的方法
*/
public abstract void onLoadMoreData() ;
}
從代碼中展現:通過監聽RecycleView的滑動狀态的改變和使用者是否正在向上滑動進行觸發加載更多的方法
四、接下來,我們去Activity中去看看如何使用
public class RecycleLoadmoreActivity extends AppCompatActivity {
@InjectView(R.id.arl_rv_recycleview)
RecyclerView arlRvRecycleview;
@InjectView(R.id.arl_srl_refresh)
SwipeRefreshLayout arlSrlRefresh;
private LoadMoreAdapter loadMoreAdapter;
private ArrayList<String> dataList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycle_loadmore);
ButterKnife.inject(this);
initListener();
loadData();
initAdapter();
}
/**
* 加載監聽
*/
private void initListener() {
arlSrlRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
dataList.clear();
loadData();
loadMoreAdapter.setLoadState(loadMoreAdapter.LOADING_COMPLETE);
loadMoreAdapter.notifyDataSetChanged();
// 延時1s關閉下拉重新整理
arlSrlRefresh.postDelayed(new Runnable() {
@Override
public void run() {
if (arlSrlRefresh != null && arlSrlRefresh.isRefreshing()) {
arlSrlRefresh.setRefreshing(false);
}
}
}, 1000);
}
});
}
private void initAdapter() {
loadMoreAdapter = new LoadMoreAdapter(dataList);
arlRvRecycleview.setAdapter(loadMoreAdapter);
arlRvRecycleview.setLayoutManager(new LinearLayoutManager(this));
arlRvRecycleview.addOnScrollListener(new EndlessRecyclerOnScrollListener() {
@Override
public void onLoadMoreData() {
loadMoreAdapter.setLoadState(loadMoreAdapter.LOADING);
if (dataList.size() < 52) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
loadData();
loadMoreAdapter.setLoadState(
loadMoreAdapter.LOADING_COMPLETE);
}
});
}
},3000);
}else{
loadMoreAdapter.setLoadState(
loadMoreAdapter.LOADING_END);
}
}
});
}
/**
* 加載資料
*/
private void loadData() {
char letter = 'A';
for (int i = 0; i < 26; i++) {
dataList.add(String.valueOf(letter));
letter++;
}
}
}
源碼已經上傳到GitHub上了,歡迎Fork,覺得還不錯就Start一下吧!