关于RecycleView实现上拉加载更多的思路和方法,我相信每个人都有那么几套,
比如我
1、使用的是 BaseRecycleViewAdapterHelper 因为这个库真的帮助我们实现了好多的东西,结合Rxjava+Retrofit在项目中的使用,在不同的状态进行处理不同的业务逻辑,所以这个Adapter已经完完全全的实现了。
2、最开始选择这个库的原因是:里面可以通过几句代码实现item滑动的动画,也可以很方便的自定义动画。
3、比一般的更稳定,因为上拉会产生很多的问题,或者多滑几次会出现卡顿,不加载等问题。
好了,说了很多的废话,开始我们正题。
GitHub传送门 https://github.com/OnexZgj/OneX (包含很多的测试代码,选择RecycleView LoadMore)Button 进行查看效果
看到网上很多的Adapter的框架,我们也自己实现一个Adapter
一、先实现LoadMoreAdapter(实现RecycleViewAdapter的最基本的方式)
/**
* Created by zgj on 2017/11/6:10:37.
* des: 上拉加载更多的adapter
*/
public class LoadMoreAdapter extends RecyclerView.Adapter {
private List 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 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 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一下吧!