关于recyclerview分页功能的实现方法:
一、自定义RecyclerView
有人已经造好轮子里,泡网大神,XRecyclerView,Github链接
二、自定义OnScrollListener
我是参考csdn上的这篇博文,让RecyclerView支持加载更多(Endless RecyclerView)
使用方法很简单,如下
mRecyclerView.addOnScrollListener(new OnRecyclerLoadMoreListener() {
@Override
public void onLoadMore() {
calculate();
loadListMore();
}
});
calculate()这个方法就是用来计算start和limit值的
private int start = 0; // 当前页数
private int limit = 5; // 为每页显示数据数目
private int totalCount;// 列表总条数,在第一次加载列表数据接口时就应该拿到值了
private void calculate() {
int current = adapter.getItemCount();
if (current + limit < totalCount) {
start = current;
} else {
start = current;
limit = totalCount - current;
}
}
loadListMore方法就是用来加载更多网络数据的,方法内容和初次进来加载列表数据的方法基本一致,只是把返回的数组放到一个新的集合list中去(比如listMore),然后再使用初次加载列表数据的listData的addAll方法把listMore全部加进去,list就由原来的5条变成了10条,同时去更新adapter,这样就实现了基本的上拉加载更多功能。
至于recyclerview的下拉刷新功能,只需要靠swiperefreshlayout的setOnRefreshListener方法就好了
————————————————–久违的分割线——————————————-
RecyclerView作为ListView和GridView的替代者,这几天花点时间学习了下,虽然已经出来好久了,但是我现在才开始了解它,真是愧疚愧疚,谨以此文来记录下学习过程中的心得体会。
国际惯例,先上一张要实现的效果图:
看起来比较简单,大概涉及到以下几个功能点:
1、RecyclerView的嵌套
2、配合SwipeRefreshLayout使用实现的下拉刷新、上拉加载更多(分页)效果
3、添加分隔线、添加item点击事件、通用ViewHolder及适配器
4、GridLayoutManager高度自适应以及相等的间隔:目前是根据list大小先固定三种高度
5、添加headerView,参考这里
6、侧滑功能(未添加)–> com.daimajia.swipelayout:library
7、拖拽排序功能(未添加)–> DragSortListViewLibrary
主要代码如下(RecyclerView滑动监听参考链接):
mRecyclerView = (RecyclerView) findViewById(R.id.aboutUs_recycleView);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.recycleview_swiperefresh);
// RecycleView初始化配置
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(
TestRecyclerViewActivity.this, DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setHasFixedSize(true);// 其实我还没完全明白这个设置的作用
// 设置下拉刷新圆圈图标可变换的颜色,默认为黑色
swipeRefreshLayout.setColorSchemeResources(R.color.blue,
R.color.orange,
R.color.red);
// 下拉刷新
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
start = 0;
limit = 5;
loadData();
}
});
// 上拉加载更多
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
boolean isSlidingToLast = false;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
LinearLayoutManager manager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int lastVisibleItem = manager.findLastCompletelyVisibleItemPosition();
int totalCount = manager.getItemCount();
if (lastVisibleItem == (totalCount - 1) && isSlidingToLast) {
calculate();
loadListMore();
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
isSlidingToLast = true;
} else {
isSlidingToLast = false;
}
}
});
loadData();
先绑定控件,初始化RecyclerView和SwipeRefreshLayout配置,然后添加下拉刷新和上拉加载更多的监听事件,最后加载默认数据
为了测试方便,加载数据都是写死的,如下:
private void calculate() {
int current = adapter.getItemCount();
if (current + limit < totalCount) {
start = current;
} else {
start = current;
limit = totalCount - current;
}
}
private void loadData() {
// 加载数据
mListData.clear();
for (int i = start + limit - 1; i >= 0; i--) {
RecycleBean recycleBean = new RecycleBean();
recycleBean.setId(i);
recycleBean.setName("name" + i);
recycleBean.setContent("content" + i);
List imageList = new ArrayList<>();
for (int j = 0; j < i + 1; j++) {
RecycleImageBean imageBean = new RecycleImageBean();
imageBean.setId(j);
imageBean.setImage(sampleUrl);
imageList.add(imageBean);
}
recycleBean.setImageList(imageList);
mListData.add(recycleBean);
}
// 创建Adapter,并指定数据集
adapter = new MyRecyclerAdapter(TestRecyclerViewActivity.this, mListData);
// 绑定Adapter到RecyclerView上
mRecyclerView.setAdapter(adapter);
// 停止刷新
swipeRefreshLayout.setRefreshing(false);
adapter.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Toast.makeText(TestRecyclerViewActivity.this, "点击了item" + position, Toast.LENGTH_SHORT).show();
}
});
}
private void loadListMore() {
mListDataMore.clear();
for (int i = start; i < start + limit; i++) {
RecycleBean recycleBean = new RecycleBean();
recycleBean.setId(i);
recycleBean.setName("更多name" + i);
recycleBean.setContent("更多content" + i);
List imageList = new ArrayList<>();
for (int j = 0; j < i + 1; j++) {
RecycleImageBean imageBean = new RecycleImageBean();
imageBean.setId(j);
imageBean.setImage(sampleUrl);
imageList.add(imageBean);
}
recycleBean.setImageList(imageList);
mListData.add(recycleBean);
}
mListData.addAll(mListDataMore);
adapter.notifyDataSetChanged();
// adapter.notifyItemInserted(); // 建议使用这种更新adapter方式,带position参数
if(adapter.getItemCount() >=totalCount) {
Toast.makeText(TestRecyclerViewActivity.this, "数据全部加载完毕", Toast.LENGTH_SHORT).show();
}
}
还有就是两个adapter的代码,继承自basereyclerviewadapter,不好意思忘了在哪边搜到的这些代码,以后找到出处在补上
public class GridImageAdapter extends BaseRecyclerViewAdapter {
public GridImageAdapter(Context context, List> list) {
super(context, list);
}
@Override
public int onCreateViewLayoutID(int viewType) {
return R.layout.main_recycleview_image_item;
}
@Override
public void onBindViewHolder(RecyclerHolder holder, int position) {
RecycleImageBean item = (RecycleImageBean) list.get(position);
ImageLoader.getInstance().displayImage(item.getImage(), holder.getImageView(R.id.recycleview_image_item_iv));
}
}
public class MyRecyclerAdapter extends BaseRecyclerViewAdapter {
public MyRecyclerAdapter(Context context, List> list) {
super(context, list);
}
@Override
public int onCreateViewLayoutID(int viewType) {
return R.layout.main_recycleview_item;
}
@Override
public void onBindViewHolder(RecyclerHolder holder, int position) {
final RecycleBean item = (RecycleBean) list.get(position);
RecyclerView gridRecyclerView = holder.getRecycleview(R.id.recycleview_item_recycleView);
TextView contentTV = holder.getTextView(R.id.recycleview_item_content);
TextView timeTV = holder.getTextView(R.id.recycleview_item_time);
// RecyclerView初始化配置
gridRecyclerView.setLayoutManager(new GridLayoutManager(TestRecyclerViewActivity.this, 3));
// 设置Item增加、移除动画
gridRecyclerView.setItemAnimator(new DefaultItemAnimator());
// 代码中设置嵌套的recyclerview的高度
int gHeight = 0;
int gSize = item.getImageList().size();
if (gSize == 1 || gSize == 2 || gSize == 3) {
gHeight = (int) getResources().getDimension(R.dimen.width_45_160);
} else if (gSize == 4 || gSize == 5 || gSize == 6) {
gHeight = (int) getResources().getDimension(R.dimen.width_90_160);
} else if (gSize == 7 || gSize == 8 || gSize == 9) {
gHeight = (int) getResources().getDimension(R.dimen.width_135_160);
}
gridRecyclerView.getLayoutParams().height = gHeight;
GridImageAdapter demoAdapter = new GridImageAdapter(TestRecyclerViewActivity.this, item.getImageList());
gridRecyclerView.setAdapter(demoAdapter);
demoAdapter.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Log.i("TAG", "点击了" + item.getImageList().get(position).getImage());
}
});
contentTV.setText(item.getContent());
timeTV.setText(item.getName());
}
}
然后就是通用的ViewHolder
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Date: 2016/1/26 14:17
* Email: [email protected]
* Author: diyangxia
* Description: RecyclerView通用ViewHolder
*/
public class RVHolder extends RecyclerView.ViewHolder {
private RecyclerHolder viewHolder;
public RVHolder(View itemView) {
super(itemView);
viewHolder= RecyclerHolder.getViewHolder(itemView);
}
public RecyclerHolder getViewHolder() {
return viewHolder;
}
}
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class RecyclerHolder {
private SparseArray viewHolder;
private View view;
public static RecyclerHolder getViewHolder(View view) {
RecyclerHolder viewHolder = (RecyclerHolder) view.getTag();
if (viewHolder == null) {
viewHolder = new RecyclerHolder(view);
view.setTag(viewHolder);
}
return viewHolder;
}
private RecyclerHolder(View view) {
this.view = view;
viewHolder = new SparseArray();
view.setTag(viewHolder);
}
public T get(int id) {
View childView = viewHolder.get(id);
if (childView == null) {
childView = view.findViewById(id);
viewHolder.put(id, childView);
}
return (T) childView;
}
public View getConvertView() {
return view;
}
public TextView getTextView(int id) {
return get(id);
}
public Button getButton(int id) {
return get(id);
}
public ImageView getImageView(int id) {
return get(id);
}
public void setTextView(int id, CharSequence charSequence) {
getTextView(id).setText(charSequence);
}
public RecyclerView getRecycleview(int id) {
return get(id);
}
}
以及通用RecyclerView适配器:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import java.util.List;
/**
* Date: 2016/1/26 14:08
* Email: [email protected]
* Author: diyangxia
* Description: RecyclerView通用适配器
*/
public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter {
public List> list;
private Context context;
public BaseRecyclerViewAdapter(Context context, List> list) {
this.list = list;
this.context = context;
}
@Override
public RVHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(onCreateViewLayoutID(viewType), null);
return new RVHolder(view);
}
public abstract int onCreateViewLayoutID(int viewType);
@Override
public void onViewRecycled(final RVHolder holder) {
super.onViewRecycled(holder);
}
@Override
public void onBindViewHolder(final RVHolder holder, final int position) {
onBindViewHolder(holder.getViewHolder(), position);
if (onItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClick(null, v, holder.getPosition(), holder.getItemId());
}
});
}
}
public abstract void onBindViewHolder(RecyclerHolder holder, int position);
@Override
public int getItemCount() {
return list.size();
}
private AdapterView.OnItemClickListener onItemClickListener;
public AdapterView.OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
/**
* 添加Item点击事件
*/
public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
布局文件和两个实体类就不贴了,以上代码系搜索引擎都拼西凑而来,毕竟有大牛造好了轮子干嘛不用。
修复Scrollview嵌套了RecyclerView无法全屏滑动的问题:重写LinearLayoutManager,详见链接1 链接2