本文主要实现的是上拉加载更多功能,下拉刷新使用的是Google官方的SwipeRefreshLayout控件,但是却没有实现上拉加载。我们一般用到上拉加载功能都是在列表显示中,所以本文用SwipeRefreshLayout配合RecycleView实现上拉加载和下拉刷新功能。
下拉刷新我们用SwipeRefreshLayout原生的能力即可,主要是如何实现上拉加载呢?简单的实现思路如下:通过监听RecycleView的上拉操作,在其滚动监听状态中判断当前显示的item是不是最后一个item从而决定是否调用加载更多操作。
首先看主布局:
在RecyclerView外层套一个SwipeRefreshLayout即可
接着item的布局
footer的布局
下面就是主要的部分,adapter的实现了,代码里的注释都比较清晰了。
public class RefreshLoadRecycleAdapter extends RecyclerView.Adapter{
private ArrayList mDatas;
private final int ITEM_TYPE =0; //item布局类型
private final int FOOTER_TYPPE = 1; //footer布局类型
public static final int LOADING = 0; //加载中
public static final int LOAD_FINISH = 1; //加载完成
public static final int LOAD_END =2; //加到底
private int loadState = LOAD_FINISH;
public RefreshLoadRecycleAdapter( ArrayList datas){
mDatas = datas;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == FOOTER_TYPPE){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_layout,parent,false);
return new FooterViewHolder(view);
}else if(viewType == ITEM_TYPE){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout,parent,false);
return new ItemViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(holder instanceof ItemViewHolder){
ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
itemViewHolder.tvContent.setText(mDatas.get(position));
}else if(holder instanceof FooterViewHolder){
FooterViewHolder footerViewHolder = (FooterViewHolder)holder;
if(loadState == LOADING){
footerViewHolder.mProgressBar.setVisibility(View.VISIBLE);
footerViewHolder.tvMsg.setVisibility(View.VISIBLE);
footerViewHolder.tvBottom.setVisibility(View.GONE);
}else if(loadState == LOAD_FINISH){
footerViewHolder.mProgressBar.setVisibility(View.INVISIBLE);
footerViewHolder.tvMsg.setVisibility(View.INVISIBLE);
footerViewHolder.tvBottom.setVisibility(View.GONE);
}else if(loadState == LOAD_END){
footerViewHolder.mProgressBar.setVisibility(View.GONE);
footerViewHolder.tvMsg.setVisibility(View.GONE);
footerViewHolder.tvBottom.setVisibility(View.VISIBLE);
}
}
}
@Override
public int getItemCount() {
return mDatas.size() + 1; //加一个footer布局
}
@Override
public int getItemViewType(int positon){
if(positon + 1 == getItemCount()){ //最后一个为footer布局
return FOOTER_TYPPE;
}
return ITEM_TYPE;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
//适配gridiew 的情况
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 如果当前是footer的位置,那么该item占据n个单元格,正常情况下占据1个单元格
return getItemViewType(position) == FOOTER_TYPPE ? gridManager.getSpanCount() : 1;
}
});
}
}
//添加刷新数据
public void AddHeaderItem(ArrayList items){
mDatas.addAll(0,items);
notifyDataSetChanged();
}
//添加加载数据
public void AddFooterItem(ArrayList items){
mDatas.addAll(items);
notifyDataSetChanged();
}
/**
* 设置加载状态
* @param loadState
*/
public void setLoadState(int loadState) {
this.loadState = loadState;
notifyDataSetChanged();
}
//item 布局holder
static class ItemViewHolder extends RecyclerView.ViewHolder{
TextView tvContent;
public ItemViewHolder(View itemView) {
super(itemView);
tvContent = itemView.findViewById(R.id.tvContent);
}
}
//footer 布局holder
static class FooterViewHolder extends RecyclerView.ViewHolder{
ProgressBar mProgressBar;
TextView tvMsg;
TextView tvBottom;
public FooterViewHolder(View itemView) {
super(itemView);
mProgressBar = itemView.findViewById(R.id.progressBar);
tvMsg = itemView.findViewById(R.id.tvMsg);
tvBottom = itemView.findViewById(R.id.tvBottom);
}
}
}
接着要实现RecycleView的滑动监听,判断滑动状态实现上拉刷新.这里用抽象类继承 RecyclerView.OnScrollListener来实现
public abstract class RecycleOnscrollListener extends RecyclerView.OnScrollListener{
//用来标记是否正在向上滑动
private boolean isSlidingUp = 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) && isSlidingUp) {
//加载更多
onLoadMore();
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// 大于0表示正在向上滑动,小于等于0表示停止或向下滑动
isSlidingUp = dy > 0;
}
/**
* 加载更多回调
*/
public abstract void onLoadMore();
前期的实现都完成了,下面看怎么使用.其实主要就是实现两个监听,下拉刷新( mRefreshLayout.setOnRefreshListener)和上拉( recyclerView.addOnScrollListener)
private SwipeRefreshLayout mRefreshLayout;
private RecyclerView recyclerView;
private RefreshLoadRecycleAdapter mRecycleAdapter;
private ArrayList dataList = new ArrayList<>();
private int page = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRefreshLayout = findViewById(R.id.refreshLayout);
recyclerView = findViewById(R.id.recyclerView);
//进度条圈圈颜色
mRefreshLayout.setColorSchemeColors(Color.RED,Color.BLUE,Color.GREEN);
// mRefreshLayout.setColorSchemeResources(R.color.colorAccent);
init();
}
private void init(){
page = 0;
getData(page);
mRecycleAdapter = new RefreshLoadRecycleAdapter(dataList);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
//自定义分割线
// recyclerView.addItemDecoration(new RecycleViewDivider(this, RecycleViewDivider.LIST_VERTICAL));
recyclerView.setAdapter(mRecycleAdapter);
initListener();
}
private void initListener(){
//上拉加载
recyclerView.addOnScrollListener(new RecycleOnscrollListener(){
@Override
public void onLoadMore() {
mRecycleAdapter.setLoadState(RefreshLoadRecycleAdapter.LOADING);
if (dataList.size() <= 60) {
// 模拟获取网络数据,延时3s
new Timer().schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
page++;
getData(page);
mRecycleAdapter.setLoadState(mRecycleAdapter.LOAD_FINISH);
}
});
}
}, 3000);
} else {
// 显示加载到底的提示
page = 0;
mRecycleAdapter.setLoadState(mRecycleAdapter.LOAD_END);
}
}
});
//下拉刷新
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ArrayList headDatas = new ArrayList();
for (int i = 0; i <20 ; i++) {
headDatas.add("Heard Item "+i);
}
mRecycleAdapter.AddHeaderItem(headDatas);
//刷新完成
mRefreshLayout.setRefreshing(false); //一定记得set,不然刷新动画一直在
Toast.makeText(MainActivity.this, "更新了 "+headDatas.size()+" 条目数据", Toast.LENGTH_SHORT).show();
}
}, 3000);
}
});
}
private void getData(int page){
int ind = 20 * page;
ArrayList datas = new ArrayList<>();
for (int i = ind; i < 20 + ind; i++) {
datas.add("item " + i);
}
if(page ==0) {
dataList.addAll(datas);
}else {
mRecycleAdapter.AddFooterItem(datas);
}
}
参考https://www.jianshu.com/p/b502c5b59998
另外github有大神实现了一个比较多功能的RecyclerView侧滑菜单,Item拖拽,滑动删除Item,自动加载更多等的开源项目,有兴趣可以看看https://github.com/yanzhenjie/SwipeRecyclerView