最近因为需求问题,须要写一个列表。之前老是使用ListView,历来没有用过RecyclerView。因此此次打算尝试一下。而后就开始动手干活了。RecyclerView布局写好了。而后写adapter,一切正常。
java
发现没有分割线有点难看。准备去布局文件里面写分割线,发现竟然没有divider这个属性。后来百度了一下,原来RecyclerView设置分割线是代码中添加的。android
recyclerView.addItemDecoration(new DividerItemDecoration(context,DividerItemDecoration.VERTICAL));
如今Google已经内置了DividerItemDecoration类,之前是没有这个类的,须要咱们本身写,如今愈来愈方便了。第一个参数须要传入Context,第二个参数是分割线的类型,我这个是表示vertical。固然,若是你有须要你彻底能够设置为horizontal。你觉得这样就设置好分割线了吗?答案显而易见,没有。web
接下来,你须要在res目录下drawable的文件夹里面新建一个divider.xml文件。名字你能够按你本身的喜爱来设置。canvas
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/gray"/>
<size android:height="0.1dp"/>
</shape>
我这里gray是#D0D0D0,你们也能够本身修改。app
再而后,你须要在values文件夹里面的styles文件里面添加这样一行代码。ide
<item name="android:listDivider">@drawable/divider</item>
好,写到这里。大功告成。先运行一下看看效果。
嗯?忽然发现最后一行数据的下面也有分割线,这样不太美观。接下来咱们继续修改。svg
聪明的小伙伴可能已经知道怎么修改了。答案就是前面提到的DividerItemDecoration这个类。咱们进去看看。布局
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
public static final int VERTICAL = LinearLayout.VERTICAL;
private static final int[] ATTRS = new int[]{ android.R.attr.listDivider };
private Drawable mDivider;
/** * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}. */
private int mOrientation;
private final Rect mBounds = new Rect();
/** * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a * {@link LinearLayoutManager}. * * @param context Current context, it will be used to access resources. * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}. */
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
/** * Sets the orientation for this divider. This should be called if * {@link RecyclerView.LayoutManager} changes orientation. * * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL} */
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL && orientation != VERTICAL) {
throw new IllegalArgumentException(
"Invalid orientation. It should be either HORIZONTAL or VERTICAL");
}
mOrientation = orientation;
}
/** * Sets the {@link Drawable} for this divider. * * @param drawable Drawable that should be used as a divider. */
public void setDrawable(@NonNull Drawable drawable) {
if (drawable == null) {
throw new IllegalArgumentException("Drawable cannot be null.");
}
mDivider = drawable;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (parent.getLayoutManager() == null) {
return;
}
if (mOrientation == VERTICAL) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
@SuppressLint("NewApi")
private void drawVertical(Canvas canvas, RecyclerView parent) {
canvas.save();
final int left;
final int right;
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(ViewCompat.getTranslationY(child));
final int top = bottom - mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
canvas.restore();
}
@SuppressLint("NewApi")
private void drawHorizontal(Canvas canvas, RecyclerView parent) {
canvas.save();
final int top;
final int bottom;
if (parent.getClipToPadding()) {
top = parent.getPaddingTop();
bottom = parent.getHeight() - parent.getPaddingBottom();
canvas.clipRect(parent.getPaddingLeft(), top,
parent.getWidth() - parent.getPaddingRight(), bottom);
} else {
top = 0;
bottom = parent.getHeight();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds);
final int right = mBounds.right + Math.round(ViewCompat.getTranslationX(child));
final int left = right - mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
canvas.restore();
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
if (mOrientation == VERTICAL) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
里面有这样一个方法drawVertical,没错它就是在这个方法里面循环的绘制每一条分割线的。因此咱们只须要将for循环里面的i<childCount
改成i<childCount-1
就能够了。这里我用到的是垂直方向上的,因此drawHorizontal方法里面的数据我就没有修改。你们本身按需求修改哈。可是DividerItemDecoration这个类咱们可能不能直接修改,咱们能够新建一个类DividerItemsDecoration继承自RecyclerView.ItemDecoration,将DividerItemDecoration里面的代码copy过来,将我上面说的东西修改掉,这样就真的大功告成了。接下来运行咱们的程序,就能够看到精美的
分割线了。是否是很开心。this