RecyclerView的功能十分强大,但要为其添加分割线却不如ListView那么简单。但是RecyclerView的分割线远比ListView的灵活,那怎样优雅地为RecyclerView添加分割线呢?封装一个继承自ItemDecoration的类即可。以下为我参照多方资料封装的分割线类,希望能为广大同胞们出一份力,让各位单身狗们能够有更多的时间去撩妹。
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntDef;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class LinearDivider extends RecyclerView.ItemDecoration {
public static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL = LinearLayoutManager.VERTICAL;
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
private final SparseIntArray mDividerOffsets = new SparseIntArray();
private final SparseArray<DrawableCreator> mTypeDrawableFactories = new SparseArray<>();
@IntDef({
HORIZONTAL,
VERTICAL
})
@Retention(RetentionPolicy.SOURCE)
private @interface Orientation {
}
@Orientation
private int mOrientation;
private Drawable mDivider;
private boolean isIncludeEdge;
private int mSize;
public LinearDivider(Context context) {
this.isIncludeEdge = false;
resolveDivider(context);
setOrientation(VERTICAL);
}
private void resolveDivider(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
public LinearDivider(int mColor, int mSize) {
this.mDivider = new ColorDrawable(mColor);
this.mSize = mSize;
this.isIncludeEdge = false;
setOrientation(VERTICAL);
}
public LinearDivider(int mColor, int mSize, @Orientation int orientation) {
this.isIncludeEdge = false;
this.mDivider = new ColorDrawable(mColor);
this.mSize = mSize;
setOrientation(orientation);
}
public LinearDivider(int mColor, int mSize, boolean isIncludeEdge) {
this.isIncludeEdge = isIncludeEdge;
this.mDivider = new ColorDrawable(mColor);
this.mSize = mSize;
setOrientation(VERTICAL);
}
public LinearDivider(int mColor, int mSize, @Orientation int orientation, boolean isIncludeEdge) {
this.isIncludeEdge = isIncludeEdge;
this.mDivider = new ColorDrawable(mColor);
this.mSize = mSize;
setOrientation(orientation);
}
public void setOrientation(@Orientation int orientation) {
mOrientation = orientation;
}
public void setDivider(Drawable divider) {
this.mDivider = divider;
}
public void setColor(int mColor) {
this.mDivider = new ColorDrawable(mColor);
}
public void setSize(int mSize) {
this.mSize = mSize;
}
public void setIncludeEdge(boolean isIncludeEdge) {
this.isIncludeEdge = isIncludeEdge;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL) {
drawVerticalDividers(c, parent);
} else {
drawHorizontalDividers(c, parent);
}
}
private void drawVerticalDividers(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++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final Drawable divider = getDivider(parent, params.getViewAdapterPosition());
final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
final int bottom = top + mSize;
mDividerOffsets.put(params.getViewAdapterPosition(), mSize);
if (isIncludeEdge && i == 0) {
final int edgeTop = child.getTop() - params.topMargin - mSize;
final int edgeBottom = child.getTop() - params.topMargin;
divider.setBounds(left, edgeTop, right, edgeBottom);
divider.draw(c);
}
if (isIncludeEdge || i != childCount - 1) {
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}
}
}
private void drawHorizontalDividers(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++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final Drawable divider = getDivider(parent, params.getViewAdapterPosition());
final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
final int right = left + mSize;
mDividerOffsets.put(params.getViewAdapterPosition(), mSize);
if (isIncludeEdge && i == 0) {
final int edgeLeft = child.getLeft() - params.leftMargin - mSize;
final int edgeRight = child.getLeft() - params.leftMargin;
divider.setBounds(edgeLeft, top, edgeRight, bottom);
divider.draw(c);
}
if (isIncludeEdge || i != childCount - 1) {
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
final int adapterPosition = parent.getChildAdapterPosition(view);
int edge = 0;
if (isIncludeEdge) {
if (adapterPosition == 0) {
edge = mSize;
}
} else {
if (adapterPosition == parent.getAdapter().getItemCount() - 1) {
return;
}
}
if (mDividerOffsets.indexOfKey(adapterPosition) < 0) {
mDividerOffsets.put(adapterPosition, mSize);
}
if (mOrientation == VERTICAL) {
outRect.set(0, edge, 0, mDividerOffsets.get(parent.getChildAdapterPosition(view)));
} else {
outRect.set(edge, 0, mDividerOffsets.get(parent.getChildAdapterPosition(view)), 0);
}
}
private Drawable getDivider(RecyclerView parent, int adapterPosition) {
final RecyclerView.Adapter adapter = parent.getAdapter();
final int itemType = adapter.getItemViewType(adapterPosition);
final DrawableCreator drawableCreator = mTypeDrawableFactories.get(itemType);
if (drawableCreator != null) {
return drawableCreator.create(parent, adapterPosition);
}
return mDivider;
}
interface DrawableCreator {
Drawable create(RecyclerView parent, int adapterPosition);
}
}
注意,这个分割线只供使用LinearLayoutManager的RecyclerView使用,方向可以是水平的,也可以是竖直的。里面定义了好几种构造方法,可以直接传一个int型的color和int型的size,就可以创建一个指定颜色和指定宽度的分割线了,也可以通过setDivider传入一个drawable的参数来创建自定义样式的分割线,还可以再传入方向orientation和边界是否有分割线isIncludeEdge的参数直接对分割线进行定制,最后再调recyclerView.addItemDecoration(创建的分割线)就可以了。
觉得好用还请点个赞哟。