在项目中我们会用到各种列表样式,之前我们用的是ListView或者GridView实现。但自从RecyclerView出现之后,基本上都是用RecyclerView,ListView和GridView在现在项目中基本上是弃之不用。为什么RecyclerView会如此火热呢,因为该控件整合了ListView、GridView的特点,而且最大的优点是可以很方便实现瀑布流效果,因此RecyclerView受到越来越多的开发者重视。今天先从入门使用开始
一、基本使用
1. 引入RecyclerView
由于该控件并不在Andorid SDK中的,而是在support v7包中,因此我们要手动添加该控件。
在build.gradle中添加如下依赖:
compile 'com.android.support:recyclerview-v7:24.0.0'
我们要先来认识几个它常用的内部类:
1、RecyclerView.Adapter:抽象类,为RecyclerView提供数据,一般根据不同的业务需求来编写具体的实现类。
2、RecyclerView.LayoutManager:抽象类,主要用于测量RecyclerView的子Item,以及根据不同的布局方式来实现Item的布局效果,v 7包自带的实现类有:LinearLayoutManager、StaggeredGridLayoutManager、GridLayoutManager。
3、RecyclerView.ItemDecoration:抽象类,这个主要用于不同的Item之间添加分割线(可选)。官方没有实现类,所以如果要添加分割线,我们需要手动实现这个抽象类。
4、RecyclerView.ItemAnimator:抽象类,这个主要用于当一个item添加或者删除的时候出现的动画效果,官方提供一个默认的实现类。如果想要使我们的RecyclerView在添加、删除数据的时候有炫酷的动画,可以实现这个抽象类。
2.设置recyclerView的布局管理
// LinearLayoutManager -> ListView风格
// GridLayoutManager -> GridView风格
// StaggeredGridLayoutManager -> 瀑布流风格
LinearLayoutManager linearLayoutManager = new
LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
3.适配器Adapter编写
class SimpleAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
private List<String> mData;
private LayoutInflater mInflater;
public HomeAdapter(Context context, List<String> datas) {
mInflater = LayoutInflater.from(context);
mData = datas;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(mInflater.inflate(
R.layout.item, parent, false));
return holder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv.setText(mData.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
tv = (TextView) view.findViewById(R.id.id_num);
}
}
}
4.设置
mAdapter = new SimpleAdapter (this, mDatas);
mRecyclerView.setAdapter(mAdapter);
二、分割线
RecyclerView并不像ListView,它没有支持divider这样的属性,当然在创建item布局的时候可以直接写在布局中,但是这种方式不够优雅。分割线我们利用RecyclerView的addItemDecoration(ItemDecoration fromHtml) 属性;
那么ItemDecoration 是什么我们来看一下:
public class SimpleDecoration extends RecyclerView.ItemDecoration {
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
//onDraw()我们可以直接去绘制,绘制什么都可以因为有Canvas ,但一般都是绘制Drawable
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//这里我一般指定偏移量就可以了,就是分割线占多少高度,或者说是画在什么位置
}
}
具体实现;
public class SimpleDecoration extends RecyclerView.ItemDecoration {
private Paint mPaint;
public SimpleDecoration (int color) {
// 直接绘制颜色 只是用来测试
mPaint = new Paint();
mPaint.setColor(color);
mPaint.setAntiAlias(true);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
// 获取需要绘制的区域
Rect rect = new Rect();
rect.left = parent.getPaddingLeft();
rect.right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount; i++) {
View childView = parent.getChildAt(i);
rect.top = childView.getBottom();
rect.bottom = rect.top + 20;
// 直接利用Canvas去绘制一个矩形 在留出来的地方
c.drawRect(rect, mPaint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// 在每个子View的下面留出20px来画分割线
outRect.bottom += 20;
}
}
接下来你就可以看一下效果,但是我们最终使用一般使用Drawable去画,所以我们必须改造上面类
public class SimpleDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public SimpleDecoration (Drawable divider) {
// 利用Drawable绘制分割线
mDivider = divider;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
// 计算需要绘制的区域
Rect rect = new Rect();
rect.left = parent.getPaddingLeft();
rect.right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount; i++) {
View childView = parent.getChildAt(i);
rect.top = childView.getBottom();
rect.bottom = rect.top + mDivider.getIntrinsicHeight();
// 直接利用Canvas去绘制
mDivider.draw(canvas);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// 在每个子View的下面留出来画分割线
outRect.bottom += mDivider.getIntrinsicHeight();
}
}
接下来新建xml文件
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="2dp" />
<solid android:color="@color/item_divider" />
</shape>
三、设置监听
给条目设置点击和长按事件,RecyclerView本身没有提供监听的方法,只能靠我们自己去实现
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {
// 省略其他的代码 ......
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// 省略其他的代码 ......
// 设置点击和长按事件
if (mItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(position);
}
});
}
if (mLongClickListener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return mLongClickListener.onLongClick(position);
}
});
}
}
// 省略其他的代码 ......
/*
* 给条目设置点击和长按事件
*/
public OnItemClickListener mItemClickListener;
public OnLongClickListener mLongClickListener;
public void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.mItemClickListener = itemClickListener;
}
public void setOnLongClickListener(OnLongClickListener longClickListener) {
this.mLongClickListener = longClickListener;
}
public interface OnItemClickListener {
public void onItemClick(int position);
}
public interface OnLongClickListener {
public boolean onLongClick(int position);
}
}
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。