今天总结一下RecyclerView 使用LinearLayoutManager的下拉刷新和上拉加载。
下拉刷新参考网址:github地址https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
关于下拉刷新结合上拉加载的更多的例子请参考这个网址:
https://github.com/shucc/RecyclerViewDemo
我所做的只是通过学习上面的内容自己做一些总结。先看看效果
以上就是效果,接下来看代码
1,定义两个接口OnLoadMoreListener.java和OnItemClickListener.java
**
* 用来处理加载更多事件
*/
public interface OnLoadMoreListener {
void onLoadMore();
}
/**
* 用来处理点击事件
*/
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
2自定义抽象类 MyLoadMoreAdapter 继承自RecyclerView.Adapter
package com.example.loadmoredemo;
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.LinearLayout;
import android.widget.TextView;
/**
* Created by Administrator on 2016/8/10.
*/
public abstract class MyLoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int LOAD_MORE_ITEM = -100;
private RecyclerView mRecyclerView;
private OnLoadMoreListener onLoadMoreListener;
private boolean loading = true;
private int visibleThreshold = 1;
private int lastVisibleItem, totalItemCount;
//正在加载中item position
private int loadMorePos = -1;
//是否全部加载完成
private boolean isLoadAll = false;
//加载更多的ViewHolder
private FootViewHolder footViewHolder;
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public MyLoadMoreAdapter(RecyclerView recyclerView, final OnLoadMoreListener onloadMoreListener) {
this.mRecyclerView = recyclerView;
this.onLoadMoreListener = onloadMoreListener;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)
&& dy > 0 && !isLoadAll) {
loading = true;
loadMorePos = getItemCount() - 1;
notifyItemInserted(getItemCount() - 1);
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
}
}
});
} else {
//其他的layoutManger
}
}
public final void reset() {
loading = false;
if (loadMorePos != -1) {
notifyItemRemoved(loadMorePos);
} else {
notifyDataSetChanged();
}
}
/**
* 判读数据是否加载完毕,显示不同的布局
* @param loadAll
*/
public final void setLoadAll(boolean loadAll) {
if (footViewHolder == null) {
View view = LayoutInflater.from(mRecyclerView.getContext()).inflate(R.layout.footer_view_load_more, null);
footViewHolder = new FootViewHolder(view);
}
isLoadAll = loadAll;
if (isLoadAll && footViewHolder != null) {
footViewHolder.mLLLoadNow.setVisibility(View.INVISIBLE);
footViewHolder.mTxtLoadMore.setVisibility(View.VISIBLE);
} else if (footViewHolder != null) {
footViewHolder.mLLLoadNow.setVisibility(View.VISIBLE);
footViewHolder.mTxtLoadMore.setVisibility(View.INVISIBLE);
}
if (!isLoadAll) {
loadMorePos = -1;
}
}
/**
* 如果position大于List的大小,说明正在加载
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
if (position >= getDataSize()) {
return LOAD_MORE_ITEM;
}
return super.getItemViewType(position);
}
//抽象出一个方法用来返回和adapter绑定的List的size的大小
abstract int getDataSize();
@Override
public int getItemCount() {
if (loading) {
//如果正在加载更多 返回List.size()+1
return getDataSize() + 1;
}
return getDataSize();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (footViewHolder == null) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_view_load_more, parent, false);
footViewHolder = new FootViewHolder(view);
}
return footViewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
//在这里处理RecyclerView的item的点击事件
if (!(holder instanceof FootViewHolder) && onItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onItemClick(view, position);
}
});
}
}
/**
* 底部加载的布局
*/
protected class FootViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLLLoadNow;
private TextView mTxtLoadMore;
public FootViewHolder(View itemView) {
super(itemView);
mLLLoadNow = (LinearLayout) itemView.findViewById(R.id.footer_view_load_now);
mTxtLoadMore = (TextView) itemView.findViewById(R.id.footer_view_load_all);
}
}
}
3 定义一个MyAdapter继承自 MyLoadMoreAdapter。内部的实现很简单,就不写注释了
package com.example.loadmoredemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* Created by Administrator on 2016/8/10.
*/
public class MyAdapter extends MyLoadMoreAdapter {
List<String> dataList;
private Context context;
public MyAdapter(RecyclerView recyclerView, List<String> list, OnLoadMoreListener onloadMoreListener) {
super(recyclerView, onloadMoreListener);
this.dataList = list;
Log.e("tag","dataList.size()"+dataList.size());
context = recyclerView.getContext();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == LOAD_MORE_ITEM) {
return super.onCreateViewHolder(parent, viewType);
} else {
View itemView = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
return new MyHolder(itemView);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyHolder && position < dataList.size()) {
((MyHolder) holder).textView.setText(dataList.get(position));
}
}
@Override
int getDataSize() {
if (dataList == null) {
return 0;
} else {
return dataList.size();
}
}
class MyHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textView);
}
}
}
4MainActivity 的 布局文件,涉及下拉刷新控件PtrClassicFrameLayout的使用,引入很简单,在你的module 的build.gradle 文件中加上一行
compile 'in.srain.cube:ultra-ptr:1.0.11'
MainActivity 的 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<in.srain.cube.views.ptr.PtrClassicFrameLayout xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/myPtrFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
cube_ptr:ptr_duration_to_close="300"
cube_ptr:ptr_duration_to_close_header="2000"
cube_ptr:ptr_keep_header_when_refresh="true"
cube_ptr:ptr_pull_to_fresh="false"
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
cube_ptr:ptr_resistance="1.7">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textView" />
</in.srain.cube.views.ptr.PtrClassicFrameLayout>
</RelativeLayout>
在代码中实现下拉刷新和上拉加载
package com.example.loadmoredemo;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import in.srain.cube.views.ptr.PtrClassicFrameLayout;
import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout;
public class MainActivity extends AppCompatActivity {
MyAdapter adapter;
List<String> dataList = new ArrayList<>();
RecyclerView recyclerView;
int page = 1;
PtrClassicFrameLayout ptrFrameLayout;//下拉刷新控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ptrFrameLayout = (PtrClassicFrameLayout) findViewById(R.id.myPtrFrameLayout);
ptrFrameLayout.setPtrHandler(new PtrDefaultHandler() {
//检查是否可以刷新
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
}
//下拉刷新的时候会调用这个方法,每次下拉刷新都要把page重置为1
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
page = 1;
if (adapter != null) {
adapter.setLoadAll(false);
}
getData();
}
});
/**
* 延迟500毫秒后ptrFrameLayout自动刷新会调用checkCanDoRefresh(PtrFrameLayout frame, View content, View header)
* 检查是否可以刷新,如果可以,就调用onRefreshBegin(PtrFrameLayout frame)
*/
ptrFrameLayout.postDelayed(new Runnable() {
@Override
public void run() {
ptrFrameLayout.autoRefresh();
}
}, 500);
}
/**
* 给recyclerView设置适配器
*/
public void setAdapter() {
Log.e("tag", "size" + dataList.size());
if (adapter == null) {
adapter = new MyAdapter(recyclerView, dataList, new OnLoadMoreListener() {
@Override
public void onLoadMore() {
//每次上拉加载更多之前要把page++
page++;
//每次上拉加载更多之前设置setLoadAll(false)
if (adapter != null) {
adapter.setLoadAll(false);
}
getData();
}
});
recyclerView.setAdapter(adapter);
}
//更新适配器
adapter.reset();
//如果正在下拉刷新的话,结束下拉刷新
if (ptrFrameLayout.isRefreshing()) {
ptrFrameLayout.refreshComplete();
}
}
public void getData() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (page == 1) {
dataList.clear();
for (int i = 0; i < 25; i++) {
dataList.add("string" + i);
}
setAdapter();
} else {
if (page > 3) {
if (adapter != null) {
adapter.setLoadAll(true);
}
} else {
for (int i = 22; i < 33; i++) {
dataList.add("string" + i);
}
setAdapter();
}
}
}
}, 2000);
}
}
以上就实现了RecyclerView 的下拉刷新和上拉加载,关于上拉加载和下拉刷新的更好的实现请移步:https://github.com/Chanven/CommonPullToRefresh
总结:对于recyclerView很多原理理解的还不是很深刻,以后会继续研究。附上代码下载地址:http://download.csdn.net/detail/leilifengxingmw/9606117