这是之前在ListView类中使用divider和dividerHeight参数实现的一个例子:
<ListView
android:id="@+id/activity_home_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/transparent"
android:dividerHeight="8dp"/>
然而,在RecyclerView类中我没有看到这样的可能性。
<android.support.v7.widget.RecyclerView
android:id="@+id/activity_home_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
在这种情况下,是否可以定义边距和/或直接添加自定义分隔符视图到列表项的布局中,或者是否有更好的方法来实现我的目标?
我从一个旧的要点中分叉了DividerItemDecoration,并简化了它以适应我的用例,我还修改了它,以在ListView中绘制的方式绘制分隔符,包括在最后一个列表项之后的分隔符。这也会处理垂直的ItemAnimator动画:
1)将这个类添加到你的项目中:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable divider;
public DividerItemDecoration(Context context) {
try {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
divider = a.getDrawable(0);
a.recycle();
} catch (Resources.NotFoundException e) {
// TODO Log or handle as necessary.
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (divider == null) return;
if (parent.getChildAdapterPosition(view) < 1) return;
if (getOrientation(parent) == LinearLayoutManager.VERTICAL)
outRect.top = divider.getIntrinsicHeight();
else
throw new IllegalArgumentException("Only usable with vertical lists");
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (divider == null) {
super.onDrawOver(c, parent, state);
return;
}
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 int size = divider.getIntrinsicHeight();
final int top = (int) (child.getTop() - params.topMargin - size + child.getTranslationY());
final int bottom = top + size;
divider.setBounds(left, top, right, bottom);
divider.draw(c);
if (i == childCount - 1) {
final int newTop = (int) (child.getBottom() + params.bottomMargin + child.getTranslationY());
final int newBottom = newTop + size;
divider.setBounds(left, newTop, right, newBottom);
divider.draw(c);
}
}
}
private int getOrientation(RecyclerView parent) {
if (!(parent.getLayoutManager() instanceof LinearLayoutManager))
throw new IllegalStateException("Layout manager must be an instance of LinearLayoutManager");
return ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
}
}
2)添加装饰器到你的RecylerView:
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
public class VerticalItemDecoration extends RecyclerView.ItemDecoration {
private boolean verticalOrientation = true;
private int space = 10;
public VerticalItemDecoration(int value, boolean verticalOrientation) {
this.space = value;
this.verticalOrientation = verticalOrientation;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
// Skip first item in the list
if (parent.getChildAdapterPosition(view) != 0) {
if (verticalOrientation) {
outRect.set(space, 0, 0, 0);
} else if (!verticalOrientation) {
outRect.set(0, space, 0, 0);
}
}
}
}
mCompletedShippingRecyclerView.addItemDecoration(new VerticalItemDecoration(20,false));
只需添加
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL));
此外,您可能还需要添加依赖项
实现“com.android.support: recyclerview-v7:28.0.0”
为了自定义它,你可以添加一个自定义drawable:
DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider));
你可以自由地使用任何自定义绘图,例如:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/colorPrimary"/>
<size android:height="0.5dp"/>
</shape>
而不是创建一个形状xml来改变分隔线的高度和颜色,你可以通过编程来创建它:
val divider = DividerItemDecoration(
context,
DividerItemDecoration.VERTICAL)
divider.setDrawable(ShapeDrawable().apply {
intrinsicHeight = resources.getDimensionPixelOffset(R.dimen.dp_15)
paint.color = Color.RED // Note:
// Currently (support version 28.0.0), we
// can not use tranparent color here. If
// we use transparent, we still see a
// small divider line. So if we want
// to display transparent space, we
// can set color = background color
// or we can create a custom ItemDecoration
// instead of DividerItemDecoration.
})
recycler_devices.addItemDecoration(divider)
对于那些只在RecyclerView中寻找项目之间的空间的人,请参阅我的方法,在所有项目之间获得相等的空间,除了在第一个和最后一个项目中,我给出了较大的填充。我只应用填充左/右在水平的LayoutManager和顶部/底部在垂直的LayoutManager。
public class PaddingItemDecoration extends RecyclerView.ItemDecoration {
private int mPaddingPx;
private int mPaddingEdgesPx;
public PaddingItemDecoration(Activity activity) {
final Resources resources = activity.getResources();
mPaddingPx = (int) resources.getDimension(R.dimen.paddingItemDecorationDefault);
mPaddingEdgesPx = (int) resources.getDimension(R.dimen.paddingItemDecorationEdge);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
final int itemPosition = parent.getChildAdapterPosition(view);
if (itemPosition == RecyclerView.NO_POSITION) {
return;
}
int orientation = getOrientation(parent);
final int itemCount = state.getItemCount();
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
/** Horizontal */
if (orientation == LinearLayoutManager.HORIZONTAL) {
/** All positions */
left = mPaddingPx;
right = mPaddingPx;
/** First position */
if (itemPosition == 0) {
left += mPaddingEdgesPx;
}
/** Last position */
else if (itemCount > 0 && itemPosition == itemCount - 1) {
right += mPaddingEdgesPx;
}
}
/** Vertical */
else {
/** All positions */
top = mPaddingPx;
bottom = mPaddingPx;
/** First position */
if (itemPosition == 0) {
top += mPaddingEdgesPx;
}
/** Last position */
else if (itemCount > 0 && itemPosition == itemCount - 1) {
bottom += mPaddingEdgesPx;
}
}
if (!isReverseLayout(parent)) {
outRect.set(left, top, right, bottom);
} else {
outRect.set(right, bottom, left, top);
}
}
private boolean isReverseLayout(RecyclerView parent) {
if (parent.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
return layoutManager.getReverseLayout();
} else {
throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager.");
}
}
private int getOrientation(RecyclerView parent) {
if (parent.getLayoutManager() instanceof LinearLayoutManager) {
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
return layoutManager.getOrientation();
} else {
throw new IllegalStateException("PaddingItemDecoration can only be used with a LinearLayoutManager.");
}
}
}
文件dimens.xml
<resources>
<dimen name="paddingItemDecorationDefault">10dp</dimen>
<dimen name="paddingItemDecorationEdge">20dp</dimen>
</resources>