你想要控制其显示的方式,请通过布局管理器LayoutManager;
你想要控制Item间的间隔(可绘制),请通过ItemDecoration;
你想要控制Item增删的动画,请通过ItemAnimator;
你想要控制点击、长按事件,不好意思你得自己写喽;
鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码:
我添加的依赖是:compile 'com.android.support:recyclerview-v7:24.0.0+'
mRecyclerView = findView(R.id.id_recyclerview);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, OrientationHelper.HORIZONTAL, false);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3, OrientationHelper.VERTICAL, false);
StaggeredGridLayoutManager sglm = newGridLayoutManager和StaggeredGridLayoutManager(4, OrientationHelper.VERTICAL);
mRecyclerView.setLayoutManager(gridLayoutManager);//设置布局管理器
mRecyclerView.setAdapter(adapter); //设置adapter
mRecyclerView.setItemAnimator(new DefaultItemAnimator());//添加默认Item增删动画而非初始化时的动画
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.HORIZONTAL_LIST));
RecyclerView的分割线的设置:
RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,而且RecyclerView并没有像ListView一样有divide属性,
RecyclerView的分割线需要自己去设置,首先需要准备一个分割线类来实现ItemDecoration:
public static abstract class ItemDecoration {
public void onDraw(Canvas c, RecyclerView parent, State state) {
onDraw(c, parent);
}
public void onDrawOver(Canvas c, RecyclerView parent, State state) {
onDrawOver(c, parent);
}
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
parent);
}
@Deprecated
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
outRect.set(0, 0, 0, 0);
}
当我们调用mRecyclerView.addItemDecoration()
方法添加decoration的时候,RecyclerView在绘制的时候,去会绘制decorator,即调用该类的onDraw和onDrawOver方法,
- onDraw方法先于drawChildren
- onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。
- getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。
接下来我们看一个RecyclerView.ItemDecoration
的实现类,该类很好的实现了RecyclerView添加分割线,我们先来看使用LinearLayoutManager时定义的分割线实现类:
/**
* 描述:该类用于RecyclerView采用LinearLayoutManager时的分割线设置
*/
public class RecycleLinearItemDecoration extends RecyclerView.ItemDecoration {
/**
* android.R.attr.listDivider:这是系统自带的分割线,可以找到Application theme,在theme中
* 添加<item name="android:listDivider">@drawable/divider_bg</item>来设计自己的分割线
* */
private final int[] ATTRS = new int[]{android.R.attr.listDivider};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public RecycleLinearItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) { //系统自带Canvas
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) { //注意这里的childCount是否需要-1
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;//item的下边开始设置分割线
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) { //注意这里的childCount是否需要-1
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin; //item的右边开始设置分割线
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
//通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator,Intrinsic:固有的
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
该实现类可以看到通过读取系统主题中的 Android.R.attr.listDivider
作为Item间的分割线,并且支持横向和纵向。如果你不清楚它是怎么做到的读取系统的属性用于自身,请参考我的另一篇博文: