90 votes

RecyclerView supprimer le séparateur / décorateur après le dernier élément

J'ai un assez simple RecyclerView. Voici comment je règle le diviseur

 DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.news_divider));
recyclerView.addItemDecoration(itemDecorator);
 

Et ceci est 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>
 

Le problème est que, pour une raison stupide, le séparateur n’est pas simplement créé entre les éléments. Mais aussi après le dernier article. Et je le veux seulement entre les articles pas après chaque article.

Avez-vous une idée de comment empêcher le séparateur de s'afficher après le dernier élément?

A bientôt et merci

134voto

Bhuvanesh BS Points 3786

Essayez ce code, il ne montrera pas de diviseur pour le dernier article.

 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);
        }
    }
}
 

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>
 

Définissez votre diviseur comme ceci:

 RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(context, R.drawable.divider));
recyclerView.addItemDecoration(dividerItemDecoration);
 

71voto

Maksim Turaev Points 1648

Comme proposé ici, vous pouvez étendre DividerItemDecoration comme ceci:

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 == parent.getAdapter().getItemCount() - 1) {
                outRect.setEmpty();
            } else {
                super.getItemOffsets(outRect, view, parent, state);
            }
        }
    }
);

[Mise à JOUR]
@Rebecca Hsieh a souligné:

Cela fonctionne lorsque votre point de vue dans RecyclerView ne pas avoir un fond transparent, par exemple,

<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 est appelé par RecyclerView pour mesurer la position de l'enfant. Cette solution permettra de mettre la dernière diviseur derrière le dernier élément. Par conséquent, le point de vue dans RecyclerView doit avoir un fond pour couvrir le dernier diviseur et de ce fait ressembler caché.

Autre Solution

Si vous n'aimez pas diviseur être tiré derrière, vous pouvez simplement copier ou de prolonger DividerItemDecoration de classe et de modifier son dessin comportement en modifiant for (int i = 0; i < childCount; i++) de for (int i = 0; i < childCount - 1; i++)

15voto

AbdulAli Points 400

La accepté de répondre à ne pas allouer de l'espace pour la décoration que pour ne pas surcharger getItemOffsets()

J'ai modifié les DividerItemDecoration de bibliothèque de prise en charge pour exclure la décoration depuis le dernier élément

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());
    }
}

Pour appliquer le décorateur, l'utilisation

RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(dividerDrawable);
recyclerView.addItemDecoration(dividerItemDecoration);

La source pour y compris l'orientation peut être trouvé ici https://gist.github.com/abdulalin/146f8ca42aa8322692b15663b8d508ff

4voto

savepopulation Points 142

Voici la classe DividerDecorator j'utilise dans mes applications, qui supprime la dernière ligne du dernier élément.

 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);
        }
    }
}
 

Vous pouvez le définir sur votre RecyclerView avec le code suivant:

 mRecyclerViewEvent.addItemDecoration(new DividerDecorator(context));
 

Voici le recyclerview_divider.xml

 <size
    android:width="1dp"
    android:height="1dp" />

<solid android:color="@color/DividerColor" />
 

2voto

Kuffs Points 12318

Créez votre propre Diviseur de classe (Exemple ici)

Dans le code qui attire le diviseur, vérifiez d'abord si vous êtes le dessin, le diviseur pour le dernier élément de la liste. Si si, ne pas le dessiner.

Juste être conscient que si vous substituez OnDrawOver il s'appuie sur le DESSUS de votre point de vue, y compris les barres de défilement etc. Le mieux est de coller à l' OnDraw. Beaucoup d'exemples sur Google, mais c' est un bon tutoriel sur la création de votre propre décorateurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X