关于RecyclerView的介绍网上有很多文章,这里不做过多说明,也不与ListView相比较。本文旨在基于RecyclerView实现下拉刷新和上拉加载,简单的不能再简单了。
https://github.com/honghailiang/RecyclerView_RefreshAndLoadMore
可以基于Android控件SwipeRefreshLayout实现
可以基于RecyclerView的addOnScrollListener实现,具体实现下面一一详解
布局中只需包一层SwipeRefreshLayout即可:activity_main.xml
设置监听器:MainActivity.Java
private void initListener() {
//下拉刷新
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
initData();
mAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
}, 1000);
}
});
}
监听到下拉时就重新填充数据
布局上需要,两个item布局,一个正常显示数据,另外一个显示“上拉加载更多”
重要的是在适配器中
private void initView() {
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new TestListAdapter(this, this, recyclerView, testList);
recyclerView.setAdapter(mAdapter);
}
package com.hhl.jtt.recyclerview_refreshandloadmore;
import android.content.Context;
import android.os.Handler;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by DELL on 2017/3/14.
* 适配器
*/
public class TestListAdapter extends RecyclerView.Adapter {
private LayoutInflater layoutInflater;
private static final int VIEW_ITEM = 0; //普通Item View
private static final int TYPE_FOOTER = 1; //底部FootView
private static final int TYPE_FINISH = -1; //完成FootView
private List list;
private int lastVisibleItemPosition; //最后各一个项目位置
private MyViewHolder mvHolder;
private MyProgressViewHolder mpHolder;
private RecyclerView.LayoutParams param;
private ILoadMoreData iLoadMoreData;
private int totalNum = 20;//测试总条数,利用该值判断是否加载更多,可以通过外部设置该值
public TestListAdapter(Context context, final ILoadMoreData iLoadMoreData,
RecyclerView recyclerView, List list) {
this.layoutInflater = LayoutInflater.from(context);
this.list = list;
this.iLoadMoreData = iLoadMoreData;
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//判断是否到底部了
if (newState ==RecyclerView.SCROLL_STATE_IDLE &&
lastVisibleItemPosition + 1 == getItemCount()) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//如果还有数据则加载更多
if(!getIsFinish()){
iLoadMoreData.loadMoreData();
}
}
},1000);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView,dx, dy);
//获取最后一个项目位置
lastVisibleItemPosition =linearLayoutManager.findLastVisibleItemPosition();
}
});
}
private boolean getIsFinish(){
return list.size() == totalNum;
}
/**
* 由于包含加载更多项,因此需要加1
* @return
*/
@Override
public int getItemCount() {
return list == null ? 0 : list.size()+1;
}
//根据position判断显示item的类型
@Override
public int getItemViewType(int position) {
if(position + 1 != getItemCount()){
return VIEW_ITEM;
}else{
if(getItemCount()-1 ==totalNum){
return TYPE_FINISH;
}else{
return TYPE_FOOTER;
}
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_ITEM) {
View view = layoutInflater.inflate(R.layout.item_test, parent, false);
mvHolder = new MyViewHolder(view);
return mvHolder;
} else if (viewType == TYPE_FOOTER) {
View view = layoutInflater.inflate(R.layout.item_swipe_footer, parent, false);
mpHolder = new MyProgressViewHolder(view);
return mpHolder;
} else {
//全部数据加载完,不在显示加载更多
View view = layoutInflater.inflate(R.layout.item_swipe_footer, parent, false);
mpHolder = new MyProgressViewHolder(view);
param = (RecyclerView.LayoutParams) view.getLayoutParams();
view.setVisibility(View.GONE);
param.height = 0;
param.width = 0;
view.setLayoutParams(param);
return mpHolder;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position + 1 != getItemCount()){
MyViewHolder myViewHolder = (MyViewHolder) holder;
myViewHolder.tvTestId.setText((CharSequence) list.get(position));
myViewHolder.tvTestId.setTag(position);
myViewHolder.tvTestId.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
iLoadMoreData.myOnClick(v);
}
});
}
}
/**
* 显示内容Holder
*/
class MyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_test_id)
TextView tvTestId;
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
/**
* 显示加载更多Holder
*/
class MyProgressViewHolder extends RecyclerView.ViewHolder {
public MyProgressViewHolder(View view) {
super(view);
}
}
}
可以看出实现原理非常简单,根据设置总数与list中数目比较,是否显示加载更多item
/**
* 由于包含加载更多项,因此需要加1
* @return
*/
@Override
public int getItemCount() {
return list == null ? 0 : list.size()+1;
}
//根据position判断显示item的类型
@Override
public int getItemViewType(int position) {
if(position + 1 != getItemCount()){
return VIEW_ITEM;
}else{
if(getItemCount()-1 ==totalNum){
return TYPE_FINISH;
}else{
return TYPE_FOOTER;
}
}
}
RecyclerView设置滑动监听器,只在底部显示加载更多时及有更多数据需要加载时才进行加载操作
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//判断是否到底部了,是否是加载更多item
if (newState ==RecyclerView.SCROLL_STATE_IDLE &&
lastVisibleItemPosition + 1 == getItemCount()) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//如果还有数据则加载更多
if(!getIsFinish()){
iLoadMoreData.loadMoreData();
}
}
},1000);
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView,dx, dy);
//获取最后一个项目位置
lastVisibleItemPosition =linearLayoutManager.findLastVisibleItemPosition();
}
});
判断是否有更多数据加载
private boolean getIsFinish(){
return list.size() == totalNum;
}
1)下拉刷新
2)上拉加载更多