Ich habe eine recht einfache RecyclerView.
So stelle ich den Teiler ein:
DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.news_divider));
recyclerView.addItemDecoration(itemDecorator);
Und das ist 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>
Das Problem ist aus irgendeinem Grund, dass der Teiler nicht nur zwischen den Elementen erstellt wird. Aber auch nach dem letzten Punkt. Und ich möchte es nur zwischen den Artikeln, nicht nach jedem Artikel.
Haben Sie eine Idee, wie Sie verhindern können, dass der Teiler nach dem letzten Element angezeigt wird?
android
android-recyclerview
divider
Slobodan Antonijević
quelle
quelle
Antworten:
Versuchen Sie diesen Code, er zeigt keinen Teiler für das letzte Element an. Mit dieser Methode haben Sie mehr Kontrolle über den Zeichenteiler.
public class DividerItemDecorator extends RecyclerView.ItemDecoration { private Drawable mDivider; public DividerItemDecorator(Drawable divider) { mDivider = divider; } @Override public void onDrawOver(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); } } }
divider.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>
Stellen Sie Ihren Teiler so ein:
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(context, R.drawable.divider)); recyclerView.addItemDecoration(dividerItemDecoration);
quelle
onDrawOver
stattdessenonDraw
hat den JobWenn Sie nicht wie Teiler tun gezeichnet hinter werden, können Sie einfach kopieren oder erweitern DividerItemDecoration Klasse und ihre Zeichnungsverhalten ändern durch Änderung
for (int i = 0; i < childCount; i++)
zufor (int i = 0; i < childCount - 1; i++)
Fügen Sie dann Ihren Dekorateur als hinzu
recyclerView.addItemDecoration(your_decorator);
Vorherige Lösung
Wie hier vorgeschlagen , können Sie DividerItemDecoration folgendermaßen erweitern:
recyclerView.addItemDecoration( new DividerItemDecoration(context, linearLayoutManager.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 == state.getItemCount() - 1) { outRect.setEmpty(); } else { super.getItemOffsets(outRect, view, parent, state); } } } );
@ Rebecca Hsieh wies darauf hin:
Dies funktioniert, wenn Ihre Elementansicht in RecyclerView keinen transparenten Hintergrund hat, z.
<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 wird von RecyclerView aufgerufen, um die untergeordnete Position zu messen. Diese Lösung setzt den letzten Teiler hinter den letzten Punkt. Daher sollte die Elementansicht in RecyclerView einen Hintergrund haben, der den letzten Teiler abdeckt, und dies lässt sie wie versteckt aussehen.
quelle
public class MiddleDividerItemDecoration extends DividerItemDecoration{...
.Die akzeptierte Antwort reserviert keinen Platz für die Dekoration, da sie nicht überschreibt
getItemOffsets()
Ich habe die DividerItemDecoration aus der Support-Bibliothek optimiert, um die Dekoration vom letzten Element auszuschließen
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()); } }
Verwenden Sie zum Auftragen des Dekorateurs
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(dividerDrawable); recyclerView.addItemDecoration(dividerItemDecoration);
Die Quelle für die Aufnahme der Orientierung finden Sie hier https://gist.github.com/abdulalin/146f8ca42aa8322692b15663b8d508ff
quelle
Hier ist die Kotlin-Version der akzeptierten Antwort :
class DividerItemDecorator(private val divider: Drawable?) : RecyclerView.ItemDecoration() { override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { val dividerLeft = parent.paddingLeft val dividerRight = parent.width - parent.paddingRight val childCount = parent.childCount for (i in 0..childCount - 2) { val child: View = parent.getChildAt(i) val params = child.layoutParams as RecyclerView.LayoutParams val dividerTop: Int = child.bottom + params.bottomMargin val dividerBottom = dividerTop + (divider?.intrinsicHeight?:0) divider?.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom) divider?.draw(canvas) } } }
quelle
Hier ist die
DividerDecorator
Klasse, die ich in meinen Apps verwende und die das Endergebnis des letzten Elements entfernt.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); } } }
Sie können es
RecyclerView
mit dem folgenden Code auf Ihr einstellen :mRecyclerViewEvent.addItemDecoration(new DividerDecorator(context));
Hier ist die recyclerview_divider.xml
<size android:width="1dp" android:height="1dp" /> <solid android:color="@color/DividerColor" />
quelle
Erstellen Sie Ihre eigene Divider-Klasse ( Beispiel hier )
Überprüfen Sie im Code, der den Teiler zeichnet, zuerst, ob Sie den Teiler für das letzte Element in der Liste zeichnen. Wenn ja, zeichne es nicht.
Beachten Sie jedoch, dass beim Überschreiben
OnDrawOver
die Oberseite Ihrer Ansicht einschließlich Bildlaufleisten usw. angezeigt wird. Halten Sie sich am besten daranOnDraw
. Viele Beispiele bei Google, aber dies ist ein gutes Tutorial zum Erstellen eigener Dekorateure.quelle
Erweiterungsfunktion für Kotlin:
fun RecyclerView.addItemDecorationWithoutLastDivider() { if (layoutManager !is LinearLayoutManager) return addItemDecoration(object : DividerItemDecoration(context, (layoutManager as LinearLayoutManager).orientation) { override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { super.getItemOffsets(outRect, view, parent, state) if (parent.getChildAdapterPosition(view) == state.itemCount - 1) outRect.setEmpty() else super.getItemOffsets(outRect, view, parent, state) } }) }
Sie können es leicht benutzen:
recyclerView.addItemDecorationWithoutLastDivider()
quelle
Dies ist eine angepasste Version der Android-Unterstützung, bei
DividerItemDecoration
der das letzte Element ignoriert wird:Hauptunterschied ist:
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() }
quelle
?
wo@NonNull
in Java steht.setDrawable
Methode ...Wenn Sie bereits eingestellt haben mit:
DividerItemDecoration dividerItemDecoration; dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL); mRecyclerView.addItemDecoration(dividerItemDecoration);
und wenn Sie entfernen möchten:
mRecyclerView.removeItemDecoration(dividerItemDecoration);
quelle