RecyclerView没有为绘制列表分隔符提供一个简单的接口。但实际上它为我们提供了更灵活的
划分隔线的方法。
我们使用RecyclerView。用分隔线或任何你想要的东西来装饰RecyclerView的瓷砖。这也是为什么它被称为ItemDecoration。
如《材料设计指南》所述:
分隔符位于贴图的基线内。
所以如果你想遵循材料设计指南,你不需要额外的空间来画分隔线。把它们画在瓷砖上。然而,你有权利做任何你想做的事。所以我实现了一个让你能够设置嵌入以及在瓷砖上/下面绘制的功能。
public class InsetDivider extends RecyclerView.ItemDecoration {
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Paint mPaint;
// in pixel
private int mDividerHeight;
// left inset for vertical list, top inset for horizontal list
private int mFirstInset;
// right inset for vertical list, bottom inset for horizontal list
private int mSecondInset;
private int mColor;
private int mOrientation;
// set it to true to draw divider on the tile, or false to draw beside the tile.
// if you set it to false and have inset at the same time, you may see the background of
// the parent of RecyclerView.
private boolean mOverlay;
private InsetDivider() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
}
public int getDividerHeight() {
return mDividerHeight;
}
public void setDividerHeight(int dividerHeight) {
this.mDividerHeight = dividerHeight;
}
public int getFirstInset() {
return mFirstInset;
}
public void setFirstInset(int firstInset) {
this.mFirstInset = firstInset;
}
public int getSecondInset() {
return mSecondInset;
}
public void setSecondInset(int secondInset) {
this.mSecondInset = secondInset;
}
public int getColor() {
return mColor;
}
public void setColor(int color) {
this.mColor = color;
mPaint.setColor(color);
}
public int getOrientation() {
return mOrientation;
}
public void setOrientation(int orientation) {
this.mOrientation = orientation;
}
public boolean getOverlay() {
return mOverlay;
}
public void setOverlay(boolean overlay) {
this.mOverlay = overlay;
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
protected void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft() + mFirstInset;
final int right = parent.getWidth() - parent.getPaddingRight() - mSecondInset;
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
if (parent.getChildAdapterPosition(child) == (parent.getAdapter().getItemCount() - 1)) {
continue;
}
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int bottom;
final int top;
if (mOverlay) {
bottom = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
top = bottom - mDividerHeight;
} else {
top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
bottom = top + mDividerHeight;
}
c.drawRect(left, top, right, bottom, mPaint);
}
}
protected void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop() + mFirstInset;
final int bottom = parent.getHeight() - parent.getPaddingBottom() - mSecondInset;
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
if (parent.getChildAdapterPosition(child) == (parent.getAdapter().getItemCount() - 1)) {
continue;
}
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int right;
final int left;
if (mOverlay) {
right = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
left = right - mDividerHeight;
} else {
left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
right = left + mDividerHeight;
}
c.drawRect(left, top, right, bottom, mPaint);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOverlay) {
super.getItemOffsets(outRect, view, parent, state);
return;
}
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDividerHeight);
} else {
outRect.set(0, 0, mDividerHeight, 0);
}
}
/**
* Handy builder for creating {@link InsetDivider} instance.
*/
public static class Builder {
private Context mContext;
private int mDividerHeight;
private int mFirstInset;
private int mSecondInset;
private int mColor;
private int mOrientation;
private boolean mOverlay = true; // set default to true to follow Material Design Guidelines
public Builder(Context context) {
mContext = context;
}
public Builder dividerHeight(int dividerHeight) {
mDividerHeight = dividerHeight;
return this;
}
public Builder insets(int firstInset, int secondInset) {
mFirstInset = firstInset;
mSecondInset = secondInset;
return this;
}
public Builder color(@ColorInt int color) {
mColor = color;
return this;
}
public Builder orientation(int orientation) {
mOrientation = orientation;
return this;
}
public Builder overlay(boolean overlay) {
mOverlay = overlay;
return this;
}
public InsetDivider build() {
InsetDivider insetDivider = new InsetDivider();
if (mDividerHeight == 0) {
// Set default divider height to 1dp.
insetDivider.setDividerHeight(mContext.getResources().getDimensionPixelSize(R.dimen.divider_height));
} else if (mDividerHeight > 0) {
insetDivider.setDividerHeight(mDividerHeight);
} else {
throw new IllegalArgumentException("Divider's height can't be negative.");
}
insetDivider.setFirstInset(mFirstInset < 0 ? 0 : mFirstInset);
insetDivider.setSecondInset(mSecondInset < 0 ? 0 : mSecondInset);
if (mColor == 0) {
throw new IllegalArgumentException("Don't forget to set color");
} else {
insetDivider.setColor(mColor);
}
if (mOrientation != InsetDivider.HORIZONTAL_LIST && mOrientation != InsetDivider.VERTICAL_LIST) {
throw new IllegalArgumentException("Invalid orientation");
} else {
insetDivider.setOrientation(mOrientation);
}
insetDivider.setOverlay(mOverlay);
return insetDivider;
}
}
}
你可以这样使用它:
ItemDecoration divider = new InsetDivider.Builder(this)
.orientation(InsetDivider.VERTICAL_LIST)
.dividerHeight(getResources().getDimensionPixelSize(R.dimen.divider_height))
.color(getResources().getColor(R.color.colorAccent))
.insets(getResources().getDimensionPixelSize(R.dimen.divider_inset), 0)
.overlay(true)
.build();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(divider);
我还写了一个关于如何实现ItemDecoration以及如何使用它们的演示应用程序。你可以查看我的GitHub存储库Dividers-For-RecyclerView。它有三个实现:
下隔板
叠加分隔器
插入分隔器