为RecyclerView设置divider的正确姿势

1. 关于RecyclerView的divider

ListView的divider设置起来很简单,只需要在xml中使用divider标签即可轻松实现。相比之下,RecyclerView就麻烦一点了,基本步骤如下:

  • 继承RecyclerView.ItemDecoration,复写onDraw()/onDrawOver()、getItemOffsets方法;
  • 通过mRecyclerView.addItemDecoration方法,给到RecyclerView来使用;

其中,自定义RecyclerView.ItemDecoration类,主要的套路就是在onDraw/onDrawOver方法中,通过Canvas去绘制divider,可以是Rect也可以是drawable,只要Canvas能draw出来都行。这一点相比ListView来讲,可定制性大大提高,可以满足绝大部分的需求了。

关于ItemDecoration中onDraw/onDrawOver方法,需要注意的是他们的执行顺序,这一点可以看下方法注释,介绍的很清楚了:
ItemDecoration.onDraw -> itemView的onDraw -> ItemDecoration.onDrawOver

2.举个简单的栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public DrawableItemDecoration(Context context) {
mContext = context;
mPaint = new Paint();
mPaint.setColor(0x99FF0000);
mDividerDrawable = mContext.getResources().getDrawable(R.drawable.arrow_right);
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
final int top =
(parent.getMeasuredHeight() - mDividerDrawable.getIntrinsicHeight()) / 2;
final int bottom = top + mDividerDrawable.getIntrinsicHeight();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize - 1; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + layoutParams.rightMargin + 10;
final int right = left + dividerWidth - 20;
mDividerDrawable.setBounds(left, top, right, bottom);
mDividerDrawable.draw(canvas);
}
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
@Override
public void getItemOffsets(
Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0, 0, dividerWidth, 0);
}

可以看到在onDraw方法中,在横向排列RecyclerView的每个item后面,通过Canvas画出了一个drawable来作为divider(这个drawable是一个右向的箭头,类似右尖括号的效果)。这里需要注意的一点是,getItemOffsets方法中需要设置item之间的间隔,否则画出来的divider会覆盖在itemView之上。

完~

很惭愧<br><br>只做了一点微小的工作<br>谢谢大家