RecyclerView удалить разделитель / декоратор после последнего элемента
у меня довольно простой RecyclerView. Вот как я устанавливаю делитель
DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.news_divider));
recyclerView.addItemDecoration(itemDecorator);
и это drawable / news_divider.в XML
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/white_two"/>
<size android:height="1dp"/>
</shape>
проблема по какой-то глупой причине разделитель не просто создается между элементами. Но и после последнего пункта. И я хочу, чтобы это было только между пунктами, а не после каждого пункта.
любая идея, как предотвратить показ делителя после последнего элемента?
ура и спасибо
6 ответов
попробуйте этот код, он не будет показывать разделитель для последнего элемента.
public class DividerItemDecorator extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerItemDecorator(Drawable divider) {
mDivider = divider;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int dividerLeft = parent.getPaddingLeft();
int dividerRight = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i <= childCount - 2; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int dividerTop = child.getBottom() + params.bottomMargin;
int dividerBottom = dividerTop + mDivider.getIntrinsicHeight();
mDivider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom);
mDivider.draw(canvas);
}
}
}
делитель.XML-код:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="@color/grey_300" />
</shape>
задание разделитель такой:
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(context, R.drawable.divider));
recyclerView.addItemDecoration(dividerItemDecoration);
Как предложил здесь вы можете расширить DividerItemDecoration так:
recyclerView.addItemDecoration(
new DividerItemDecoration(context, layoutManager.getOrientation()) {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
// hide the divider for the last child
if (position == parent.getAdapter().getItemCount() - 1) {
outRect.setEmpty();
} else {
super.getItemOffsets(outRect, view, parent, state);
}
}
}
);
[обновление]
@Rebecca Hsieh отметила:
этой работает когда ваш вид элемента в RecyclerView не имеет прозрачного фона, например,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#ffffff">
...
</LinearLayout>
DividerItemDecoration.getItemOffsets вызывается RecyclerView для измерения дочерней позиции. Это решение поставит последний разделитель позади последнего элемента. Поэтому вид элемента в RecyclerView должен иметь фон для покрытия последнего разделителя, и это делает его похожим на скрытый.
принятый ответ не выделяет пространство для украшения, поскольку он не переопределяет getItemOffsets()
Я настроил DividerItemDecoration из библиотеки поддержки, чтобы исключить украшение из последнего элемента
public class DividerItemDecorator extends RecyclerView.ItemDecoration {
private Drawable mDivider;
private final Rect mBounds = new Rect();
public DividerItemDecorator(Drawable divider) {
mDivider = divider;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
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 - 1; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - mDivider.getIntrinsicHeight();
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 (parent.getChildAdapterPosition(view) == state.getItemCount() - 1) {
outRect.setEmpty();
} else
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}
}
применить декоратор, используйте
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(dividerDrawable);
recyclerView.addItemDecoration(dividerItemDecoration);
источник для включения ориентации можно найти здесь https://gist.github.com/abdulalin/146f8ca42aa8322692b15663b8d508ff
здесь DividerDecorator
класс, который я использую в своих приложениях, который удаляет нижнюю строку последнего элемента.
public class DividerDecorator extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerDecorator(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.recyclerview_divider);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
вы можете установить его в свой RecyclerView
следующий код:
mRecyclerViewEvent.addItemDecoration(new DividerDecorator(context));
вот recyclerview_divider.в XML
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="@color/DividerColor" />
создайте свой собственный класс делитель (пример)
в коде, который рисует разделитель, сначала проверьте, рисуете ли вы разделитель для последнего элемента в списке. Если так,не рисуй.
просто имейте в виду, что если вы переопределите OnDrawOver
Он рисует поверх вашего вида, включая полосы прокрутки и т. д. Лучше придерживаться OnDraw
. Много примеров в Google, но этой это хороший учебник по созданию собственных декораторов.
это настроенная версия поддержки Android DividerItemDecoration
которые игнорируют последний элемент:
https://gist.github.com/mohsenoid/8ffdfa53f0465533833b0b44257aa641
основное отличие:
private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
canvas.save()
val left: Int
val right: Int
if (parent.clipToPadding) {
left = parent.paddingLeft
right = parent.width - parent.paddingRight
canvas.clipRect(left, parent.paddingTop, right,
parent.height - parent.paddingBottom)
} else {
left = 0
right = parent.width
}
val childCount = parent.childCount
for (i in 0 until childCount - 1) {
val child = parent.getChildAt(i)
parent.getDecoratedBoundsWithMargins(child, mBounds)
val bottom = mBounds.bottom + Math.round(child.translationY)
val top = bottom - mDivider!!.intrinsicHeight
mDivider!!.setBounds(left, top, right, bottom)
mDivider!!.draw(canvas)
}
canvas.restore()
}
private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
canvas.save()
val top: Int
val bottom: Int
if (parent.clipToPadding) {
top = parent.paddingTop
bottom = parent.height - parent.paddingBottom
canvas.clipRect(parent.paddingLeft, top,
parent.width - parent.paddingRight, bottom)
} else {
top = 0
bottom = parent.height
}
val childCount = parent.childCount
for (i in 0 until childCount - 1) {
val child = parent.getChildAt(i)
parent.layoutManager.getDecoratedBoundsWithMargins(child, mBounds)
val right = mBounds.right + Math.round(child.translationX)
val left = right - mDivider!!.intrinsicWidth
mDivider!!.setBounds(left, top, right, bottom)
mDivider!!.draw(canvas)
}
canvas.restore()
}