關於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一下吧!