web-dev-qa-db-fra.com

Comment ajouter des séparateurs et des espaces entre les éléments dans RecyclerView?

Voici un exemple de la manière dont cela aurait pu être fait auparavant dans la classe ListView, en utilisant les paramètres diviseur et 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"/>

Cependant, je ne vois pas une telle possibilité dans la classe 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"/>

Dans ce cas, est-il possible de définir des marges et/ou d'ajouter une vue de division personnalisée directement dans la présentation d'un élément de liste ou existe-t-il un meilleur moyen d'atteindre mon objectif?

848
EyesClear

Mise à jour d'octobre 2016

La version 25.0.0 de Android Bibliothèque de support introduite DividerItemDecoration classe:

DividerItemDecoration est un RecyclerView.ItemDecoration qui peut être utilisé comme séparateur entre les éléments d'un LinearLayoutManager. Il supporte les deux orientations HORIZONTAL et VERTICAL.

Usage:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
    layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

Réponse précédente

Certaines réponses utilisent des méthodes devenues obsolètes depuis ou ne donnent pas une solution complète. J'ai donc essayé de faire un résumé bref et à jour.


Contrairement à ListView, la classe RecyclerView n'a aucun paramètre lié au diviseur. Au lieu de cela, vous devez étendre ItemDecoration , une classe interne de RecyclerView:

ItemDecoration permet à l'application d'ajouter un dessin spécial et un décalage de présentation à des vues d'élément spécifiques à partir du jeu de données de l'adaptateur. Cela peut être utile pour tracer des séparations entre les éléments, les surbrillances, les limites de regroupement visuel, etc.

Tous les ItemDecorations sont dessinés dans l'ordre dans lequel ils ont été ajoutés, avant les vues d'élément (dans onDraw()) et après les éléments (dans onDrawOver (Canvas, RecyclerView, RecyclerView.State).

Vertical espacement ItemDecoration

Étendre ItemDecoration, ajouter un constructeur personnalisé qui prend de la place height en tant que paramètre et remplacer la méthode getItemOffsets():

public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {

    private final int verticalSpaceHeight;

    public VerticalSpaceItemDecoration(int verticalSpaceHeight) {
        this.verticalSpaceHeight = verticalSpaceHeight;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        outRect.bottom = verticalSpaceHeight;
    }
}

Si vous ne souhaitez pas insérer d'espace sous le dernier élément, ajoutez la condition suivante:

if (parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1) {
            outRect.bottom = verticalSpaceHeight;
}

Remarque: vous pouvez également modifier les propriétés outRect.top, outRect.left et outRect.right pour l'effet souhaité.

Diviseur ItemDecoration

Étendre la méthode ItemDecoration et la remplacer par la méthode onDraw():

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{Android.R.attr.listDivider};

    private Drawable divider;

    /**
     * Default divider will be used
     */
    public DividerItemDecoration(Context context) {
        final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
        divider = styledAttributes.getDrawable(0);
        styledAttributes.recycle();
    }

    /**
     * Custom divider will be used
     */
    public DividerItemDecoration(Context context, int resId) {
        divider = ContextCompat.getDrawable(context, resId);
    }

    @Override
    public void onDraw(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 + divider.getIntrinsicHeight();

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }
}

Vous pouvez appeler le premier constructeur qui utilise les attributs de diviseur Android par défaut ou le second qui utilise votre propre dessin, par exemple drawable/divider.xml.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
       Android:shape="rectangle">
    <size Android:height="1dp" />
    <solid Android:color="#ff992900" />
</shape>

Remarque: si vous souhaitez que le séparateur soit tracé sur vos éléments, remplacez la méthode onDrawOver().

Usage

Pour utiliser votre nouvelle classe, ajoutez VerticalSpaceItemDecoration ou DividerSpaceItemDecoration à RecyclerView, par exemple dans la méthode onCreateView() de votre fragment:

private static final int VERTICAL_ITEM_SPACE = 48;
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_feed, container, false);

    recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_home_recycler_view);
    linearLayoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(linearLayoutManager);

    //add ItemDecoration
    recyclerView.addItemDecoration(new VerticalSpaceItemDecoration(VERTICAL_ITEM_SPACE));
    //or
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
    //or
    recyclerView.addItemDecoration(
            new DividerItemDecoration(getActivity(), R.drawable.divider));

    recyclerView.setAdapter(...);

    return rootView;
}

Il y a aussi bibliothèque de Lucas Rocha qui est supposé simplifier le processus de décoration d'objets. Je n'ai pas encore essayé.

Parmi ses fonctionnalités sont:

  • Une collection de décorations d'articles en stock comprenant:
  • Espacement des articles Diviseurs horizontaux/verticaux.
  • Élément de liste
1109
EyesClear

Il suffit d'ajouter

recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
                DividerItemDecoration.VERTICAL));

Aussi, vous devrez peut-être ajouter la dépendance
compile 'com.Android.support:recyclerview-v7:27.1.0'

EDIT:

Pour le personnaliser un peu, vous pouvez ajouter un dessin personnalisable:

DividerItemDecoration itemDecorator = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getContext(), R.drawable.divider));

Vous êtes libre d'utiliser n'importe quel dessin personnalisable, par exemple:

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
       Android:shape="rectangle">
    <solid Android:color="@color/colorPrimary"/>
    <size Android:height="0.5dp"/>
</shape>
425
Leo Droidcoder

Puis-je attirer votre attention sur ce fichier particulier sur Github par Alex Fu: https://Gist.github.com/alexfu/0f464fc3742f134ccd1e

Il s’agit du fichier exemple DividerItemDecoration.Java "tiré directement des démonstrations de support". ( https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )

J'ai pu obtenir des lignes de séparation agréablement après l'importation de ce fichier dans mon projet et l'ajouter en tant que décoration d'élément à la vue du recycleur.

Voici à quoi ressemble onCreateView dans mon fragment contenant Recyclerview:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_recycler_view, container, false);

    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
    mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

    mRecyclerView.setHasFixedSize(true);
    mLayoutManager = new LinearLayoutManager(getActivity());
    mRecyclerView.setLayoutManager(mLayoutManager);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());

    return rootView;
}

Je suis sûr que d'autres styles peuvent être créés, mais c'est un point de départ. :)

251
Duy Nguyen

Simple ItemDecoration implémentation pour des espaces égaux entre tous les éléments.

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int space;

    public SpacesItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.right = space;
        outRect.bottom = space;

        // Add top margin only for the first item to avoid double space between items
        if(parent.getChildAdapterPosition(view) == 0) {
            outRect.top = space;
        }
    }
}
150
SergeyA

Le plus simple est de définir la couleur de fond pour RecyclerView et une couleur de fond différente pour les éléments. Voici un exemple ...

<Android.support.v7.widget.RecyclerView
    Android:background="#ECEFF1"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:scrollbars="vertical"/>

et l'élément TextView (il peut être n'importe quoi) avec la marge inférieure "x" dp ou px.

<TextView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_marginBottom="1dp"
    Android:background="#FFFFFF"/>

Le résultat ...

enter image description here

104
Madan Sapkota

Je pense que l'utilisation d'un simple diviseur vous aidera

Pour ajouter un séparateur à chaque élément:
1- Ajoutez ceci à un répertoire dessinable line_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="#999999" />
</shape>

2- Créer une classe SimpleDividerItemDecoration
J'ai utilisé cet exemple pour définir cette classe:
https://Gist.github.com/polbins/e37206fbc444207c0e92

package com.example.myapp;
import Android.content.Context;
import Android.content.res.Resources;
import Android.graphics.Canvas;
import Android.graphics.drawable.Drawable;
import Android.support.v7.widget.RecyclerView;
import Android.view.View;
import com.example.myapp.R;

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration{
private Drawable mDivider;

public SimpleDividerItemDecoration(Resources resources) {
    mDivider = resources.getDrawable(R.drawable.line_divider);
}

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


3- Dans l'activité ou le fragment qui utilise RecyclerView, dans onCreateView, ajoutez ceci:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
 RecyclerView myRecyclerView = (RecyclerView) layout.findViewById(R.id.my_recycler_view);
 myRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getResources()));
 ....
 }


4- Pour ajouter un espacement entre les éléments
il vous suffit d’ajouter une propriété de remplissage à la vue de votre article

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent" Android:layout_height="match_parent"
Android:padding="4dp"
>
..... item structure
</RelativeLayout>
41
Belal mazlom

Comme je l'ai défini ItemAnimators. Le ItemDecorator n'entre pas et ne sort pas avec l'animation.

J'ai simplement fini par avoir une ligne de vue dans mon fichier de présentation de vue d'article de chaque article. Cela a résolu mon cas. DividerItemDecoration senti être trop de sorcellerie pour un simple diviseur.

<View
    Android:layout_width="match_parent"
    Android:layout_height="1px"
    Android:layout_marginLeft="5dp"
    Android:layout_marginRight="5dp"
    Android:background="@color/lt_gray"/>
31
Javanator

C'est simple, vous n'avez pas besoin d'un code aussi compliqué

DividerItemDecoration divider = new 
DividerItemDecoration(mRVMovieReview.getContext(), 
DividerItemDecoration.VERTICAL);
divider.setDrawable(
    ContextCompat.getDrawable(getBaseContext(), R.drawable.line_divider)
);
mRVMovieReview.addItemDecoration(divider);

Ajoutez ceci dans votre dessin: line_divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" 
  Android:shape="rectangle">
    <size Android:height="1dp" />
    <solid Android:color="@Android:color/black" />
</shape>
21
Faheem

Puisqu'il n'y a pas de bonne façon de mettre en œuvre cela à l'aide de Material Design, j'ai juste fait le truc suivant pour ajouter directement un séparateur à l'élément de la liste:

<View
Android:layout_width="match_parent"
Android:layout_height="1dp"
Android:background="@color/dividerColor"/>
21
Yoann Hercouet

MISE À JOUR DU OCTOBRE 2016

Avec la bibliothèque de support v25.0.0, une implémentation par défaut des séparateurs horizontaux et verticaux de base est enfin disponible!

https://developer.Android.com/reference/Android/support/v7/widget/DividerItemDecoration.html

15
friday

Si quelqu'un cherche à ne faire qu'ajouter, disons, un espacement de 10dp entre les éléments, vous pouvez le faire en définissant un dessin sur DividerItemDecoration:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(
    recyclerView.getContext(),
    layoutManager.getOrientation()
);

dividerItemDecoration.setDrawable(
    ContextCompat.getDrawable(getContext(), R.drawable.divider_10dp)
); 

divider_10dp est une ressource pouvant être dessinée contenant:

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:shape="rectangle">
    <size Android:height="10dp"/>
    <solid Android:color="@Android:color/transparent"/>
</shape>
14
Praveen Singh

Pour ceux qui recherchent juste espaces entre les éléments dans la RecyclerView voyez mon approche où vous obtenez des espaces égaux entre tous les éléments, sauf dans les premier et dernier éléments où j'ai donné un rembourrage plus important. J'applique uniquement le remplissage à gauche/droite en horizontal LayoutManager et en haut/en bas à la verticale 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>
11
Ryan Amaral
  • Voici un hack simple pour ajouter un séparateur
  • Ajoutez simplement un arrière-plan à la mise en page de votre article de recycleur comme suit

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="@drawable/shape_border"
        Android:gravity="center"
        Android:orientation="horizontal"
        Android:padding="5dp">
    
    <ImageView
        Android:id="@+id/imageViewContactLogo"
        Android:layout_width="60dp"
        Android:layout_height="60dp"
        Android:layout_marginRight="10dp"
        Android:src="@drawable/ic_user" />
    
    <LinearLayout
        Android:id="@+id/linearLayout"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_weight="0.92"
        Android:gravity="center|start"
        Android:orientation="vertical">
    
    <TextView
        Android:id="@+id/textViewContactName"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:singleLine="true"
        Android:text="Large Text"
        Android:textAppearance="?android:attr/textAppearanceLarge" />
    
    <TextView
        Android:id="@+id/textViewStatusOrNumber"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="5dp"
        Android:singleLine="true"
        Android:text=""
        Android:textAppearance="?android:attr/textAppearanceMedium" />
    </LinearLayout>
    
    <TextView
        Android:id="@+id/textViewUnreadCount"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginRight="10dp"
        Android:padding="5dp"
        Android:text=""
        Android:textAppearance="?android:attr/textAppearanceMedium"
        Android:textColor="@color/red"
        Android:textSize="22sp" />
    
    <Button
        Android:id="@+id/buttonInvite"
        Android:layout_width="54dp"
        Android:layout_height="wrap_content"
        Android:background="@drawable/ic_add_friend" />
    </LinearLayout>
    

Créez le fichier shape_border.xml suivant dans un dossier pouvant être dessiné

  <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
      Android:shape="rectangle" >
       <gradient
        Android:angle="270"
        Android:centerColor="@Android:color/transparent"
        Android:centerX="0.01"
        Android:startColor="#000" />
    </shape>

Voici le résultat final - un RecyclerView avec diviseur.

Here is final result - a RecyclerView with divider.

11
turbandroid

En réalité, cela ne résout pas le problème, mais en guise de solution de contournement temporaire, vous pouvez définir la propriété seCompatPadding sur la carte dans votre présentation XML afin qu'elle soit identique à celle des versions antérieures à Lollipop.

card_view:cardUseCompatPadding="true"
10
Kevin Grant

Ajoutez une marge à votre vue, cela a fonctionné pour moi.

Android:layout_marginTop="10dp"

Si vous souhaitez simplement ajouter espacement égal et que vous souhaitez le faire dans XML, définissez simplement padding sur votre RecyclerView et une quantité égale de layoutMargin à l'élément que vous gonflez dans votre RecyclerView, et laissez la couleur d'arrière-plan déterminer la couleur d'espacement.

10
Quantum Mattter

J'ai créé le DividerItemDecoration à partir d'un ancien Gist et je l'ai simplifié pour s'adapter à mon cas d'utilisation. Je l'ai également modifié pour dessiner les séparateurs tels qu'ils sont dessinés dans ListView, y compris un séparateur après le dernier élément de la liste. Ceci gérera également les animations verticales ItemAnimator:

1) Ajoutez cette classe à votre projet:

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) Ajoutez le décorateur à votre RecylerView:

recyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
9
Learn OpenGL ES

Nous pouvons décorer les articles en utilisant divers décorateurs attachés à la vue de recyclage tels que le DividerItemDecoration:

Utilisez simplement ce qui suit ... extrait de la réponse de EyesClear

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

private static final int[] ATTRS = new int[]{Android.R.attr.listDivider};

private Drawable mDivider;

/**
 * Default divider will be used
 */
public DividerItemDecoration(Context context) {
    final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
    mDivider = styledAttributes.getDrawable(0);
    styledAttributes.recycle();
}

/**
 * Custom divider will be used
 */
public DividerItemDecoration(Context context, int resId) {
    mDivider = ContextCompat.getDrawable(context, resId);
}

@Override
public void onDraw(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);
    }
}

} et ensuite utiliser ce qui précède comme suit

RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
recyclerView.addItemDecoration(itemDecoration);

Cela affichera des séparations entre chaque élément de la liste, comme indiqué ci-dessous:

enter image description here

Et pour ceux qui recherchent plus de détails, consultez ce guide tilisation de RecyclerView _ CodePath Android Cliffnotes

Certaines réponses suggèrent l'utilisation de marges, mais le problème est que: Si vous ajoutez les marges supérieure et inférieure, elles apparaîtront toutes les deux ajoutées entre les éléments et elles seront trop grandes. Si vous ne faites qu'ajouter l'un ou l'autre, il n'y aura pas de marge en haut ou en bas de la liste. Si vous ajoutez la moitié de la distance en haut et la moitié en bas, les marges extérieures seront trop petites.

Ainsi, la seule solution esthétiquement correcte est le diviseur que le système sait où appliquer correctement: entre les éléments mais pas au-dessus ou au-dessous des éléments.

S'il vous plaît laissez-moi savoir des doutes dans les commentaires ci-dessous :)

6
Anudeep Samaiya

Ce lien a fonctionné comme un charme pour moi:

https://Gist.github.com/lapastillaroja/858caf1a82791b6c1a36

import Android.content.Context;
import Android.content.res.TypedArray;
import Android.graphics.Canvas;
import Android.graphics.Rect;
import Android.graphics.drawable.Drawable;
import Android.support.v7.widget.LinearLayoutManager;
import Android.support.v7.widget.RecyclerView;
import Android.util.AttributeSet;
import Android.view.View;

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;
    private boolean mShowFirstDivider = false;
    private boolean mShowLastDivider = false;


    public DividerItemDecoration(Context context, AttributeSet attrs) {
        final TypedArray a = context
                .obtainStyledAttributes(attrs, new int[]{Android.R.attr.listDivider});
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
            boolean showLastDivider) {
        this(context, attrs);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    public DividerItemDecoration(Drawable divider) {
        mDivider = divider;
    }

    public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
            boolean showLastDivider) {
        this(divider);
        mShowFirstDivider = showFirstDivider;
        mShowLastDivider = showLastDivider;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (mDivider == null) {
            return;
        }
        if (parent.getChildPosition(view) < 1) {
            return;
        }

        if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
            outRect.top = mDivider.getIntrinsicHeight();
        } else {
            outRect.left = mDivider.getIntrinsicWidth();
        }
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mDivider == null) {
            super.onDrawOver(c, parent, state);
            return;
        }

        // Initialization needed to avoid compiler warning
        int left = 0, right = 0, top = 0, bottom = 0, size;
        int orientation = getOrientation(parent);
        int childCount = parent.getChildCount();

        if (orientation == LinearLayoutManager.VERTICAL) {
            size = mDivider.getIntrinsicHeight();
            left = parent.getPaddingLeft();
            right = parent.getWidth() - parent.getPaddingRight();
        } else { //horizontal
            size = mDivider.getIntrinsicWidth();
            top = parent.getPaddingTop();
            bottom = parent.getHeight() - parent.getPaddingBottom();
        }

        for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getTop() - params.topMargin;
                bottom = top + size;
            } else { //horizontal
                left = child.getLeft() - params.leftMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }

        // show last divider
        if (mShowLastDivider && childCount > 0) {
            View child = parent.getChildAt(childCount - 1);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            if (orientation == LinearLayoutManager.VERTICAL) {
                top = child.getBottom() + params.bottomMargin;
                bottom = top + size;
            } else { // horizontal
                left = child.getRight() + params.rightMargin;
                right = left + size;
            }
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private int getOrientation(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
            return layoutManager.getOrientation();
        } else {
            throw new IllegalStateException(
                    "DividerItemDecoration can only be used with a LinearLayoutManager.");
        }
    }
}

Puis dans votre activité:

mCategoryRecyclerView.addItemDecoration(
    new DividerItemDecoration(this, null));

Ou ceci si vous utilisez un fragment:

mCategoryRecyclerView.addItemDecoration(
    new DividerItemDecoration(getActivity(), null));
6
Micro

Tiré d'une recherche google, ajoutez ceci ItemDecoration à votre RecyclerView:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

private Drawable mDivider;
private boolean mShowFirstDivider = false;
private boolean mShowLastDivider = false;


public DividerItemDecoration(Context context, AttributeSet attrs) {
    final TypedArray a = context
            .obtainStyledAttributes(attrs, new int[]{Android.R.attr.listDivider});
    mDivider = a.getDrawable(0);
    a.recycle();
}

public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
        boolean showLastDivider) {
    this(context, attrs);
    mShowFirstDivider = showFirstDivider;
    mShowLastDivider = showLastDivider;
}

public DividerItemDecoration(Drawable divider) {
    mDivider = divider;
}

public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
        boolean showLastDivider) {
    this(divider);
    mShowFirstDivider = showFirstDivider;
    mShowLastDivider = showLastDivider;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
        RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
    if (mDivider == null) {
        return;
    }
    if (parent.getChildPosition(view) < 1) {
        return;
    }

    if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
        outRect.top = mDivider.getIntrinsicHeight();
    } else {
        outRect.left = mDivider.getIntrinsicWidth();
    }
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    if (mDivider == null) {
        super.onDrawOver(c, parent, state);
        return;
    }

    // Initialization needed to avoid compiler warning
    int left = 0, right = 0, top = 0, bottom = 0, size;
    int orientation = getOrientation(parent);
    int childCount = parent.getChildCount();

    if (orientation == LinearLayoutManager.VERTICAL) {
        size = mDivider.getIntrinsicHeight();
        left = parent.getPaddingLeft();
        right = parent.getWidth() - parent.getPaddingRight();
    } else { //horizontal
        size = mDivider.getIntrinsicWidth();
        top = parent.getPaddingTop();
        bottom = parent.getHeight() - parent.getPaddingBottom();
    }

    for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
        View child = parent.getChildAt(i);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

        if (orientation == LinearLayoutManager.VERTICAL) {
            top = child.getTop() - params.topMargin;
            bottom = top + size;
        } else { //horizontal
            left = child.getLeft() - params.leftMargin;
            right = left + size;
        }
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }

    // show last divider
    if (mShowLastDivider && childCount > 0) {
        View child = parent.getChildAt(childCount - 1);
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
        if (orientation == LinearLayoutManager.VERTICAL) {
            top = child.getBottom() + params.bottomMargin;
            bottom = top + size;
        } else { // horizontal
            left = child.getRight() + params.rightMargin;
            right = left + size;
        }
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
}

private int getOrientation(RecyclerView parent) {
    if (parent.getLayoutManager() instanceof LinearLayoutManager) {
        LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
        return layoutManager.getOrientation();
    } else {
        throw new IllegalStateException(
                "DividerItemDecoration can only be used with a LinearLayoutManager.");
    }
}
}
6
gatlingxyz

Au lieu de créer un shape xml pour modifier la hauteur et la couleur du séparateur. Vous pouvez créer par programme comme

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)
5
Phan Van Linh

Je pense qu'il est nécessaire de disposer d'une réponse simple, basée sur un code, qui n'utilise pas XML.

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);

ShapeDrawable shapeDrawableForDivider = new ShapeDrawable(new RectShape());

int dividerThickness = // (int) (SomeOtherView.getHeight() * desiredPercent);
shapeDrawableForDivider.setIntrinsicHeight(dividerThickness);
shapeDrawableForDivider.setAlpha(0);

dividerItemDecoration.setDrawable(shapeDrawableForDivider);

recyclerView.addItemDecoration(dividerItemDecoration);
4
Boober Bunz

Trop tard mais pour GridLayoutManager j'utilise ceci:

public class GridSpacesItemDecoration : RecyclerView.ItemDecoration
{
    private int space;

    public GridSpacesItemDecoration(int space) {
        this.space = space;
    }

    public override void GetItemOffsets(Android.Graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
    {
        var position = parent.GetChildLayoutPosition(view);

        /// Only for GridLayoutManager Layouts
        var manager = parent.GetLayoutManager() as GridLayoutManager;

        if (parent.GetChildLayoutPosition(view) < manager.SpanCount)
            outRect.Top = space;

        if (position % 2 != 0) {
            outRect.Right = space;
        }

        outRect.Left = space;
        outRect.Bottom = space;
    }
}

Ce travail pour tout compte compte que vous avez.

Ollie.

4
Ollie Strevel

J'ai ajouté une ligne dans la liste comme ci-dessous

<View
Android:id="@+id/divider"
Android:layout_width="match_parent"
Android:layout_height="1px"
Android:background="@color/dividerColor"/>

1px va tracer la ligne mince.

Si vous souhaitez masquer le séparateur pour la dernière ligne, saisissez divider.setVisiblity(View.GONE); sur onBindViewHolder pour le dernier élément de la liste.

4
Raja Peela

Si vous souhaitez ajouter le même espace pour les éléments, le moyen le plus simple consiste à ajouter un remplissage supérieur + gauche pour RecycleView et des marges droite + inférieure aux éléments de la carte.

dimens.xml

<resources>
    <dimen name="divider">1dp</dimen>
</resources>

list_item.xml

<CardView
 Android:layout_marginBottom="@dimen/divider"
 Android:layout_marginRight="@dimen/divider">
 ...
</CardView>

list.xml

<RecyclerView
 Android:paddingLeft="@dimen/divider"
 Android:paddingTop="@dimen/divider"
/>
4
limitium

Vous pouvez ajouter facilement par programmation.

Si votre gestionnaire de mise en page est Linearlayout, vous pouvez utiliser:

DividerItemDecoration est un RecyclerView.ItemDecoration qui peut être utilisé comme séparateur entre les éléments d'un LinearLayoutManager. Il prend en charge les orientations HORIZONTAL et VERTICAL.

 mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
         mLayoutManager.getOrientation());
 recyclerView.addItemDecoration(mDividerItemDecoration);

source

4
Beyaz
public class CommonItemSpaceDecoration extends RecyclerView.ItemDecoration {
    private int mSpace = 0;
    private boolean mVerticalOrientation = true;

    public CommonItemSpaceDecoration(int space) {
        this.mSpace = space;
    }

    public CommonItemSpaceDecoration(int space, boolean verticalOrientation) {
        this.mSpace = space;
        this.mVerticalOrientation = verticalOrientation;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.top = SizeUtils.dp2px(view.getContext(), mSpace);
        if (mVerticalOrientation) {
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.set(0, SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace));
            } else {
                outRect.set(0, 0, 0, SizeUtils.dp2px(view.getContext(), mSpace));
            }
        } else {
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, 0, 0);
            } else {
                outRect.set(SizeUtils.dp2px(view.getContext(), mSpace), 0, SizeUtils.dp2px(view.getContext(), mSpace), 0);
            }
        }


    }
}

Cela ajoutera de l'espace en haut et en bas (ou à gauche et à droite) de chaque élément. Vous pourrez ensuite le définir sur votre recyclerView.

recyclerView.addItemDecoration(new CommonItemSpaceDecoration(16));

SizeUtils.Java

public class SizeUtils {
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
3
wizChen

Une solution très simple consiste à utiliser RecyclerView-FlexibleDivider

Ajouter une dépendance:

compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'

Ajoutez à votre liste de recyclage:

recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(context).build());

Et tu as fini!

3
Cristan

1.One of the Way est en utilisant cardview et recycler voir ensemble , nous pouvons facilement ajouter un effet de type diviseur. ex . https://developer.Android.com/training/material/lists-cards.html

2.et autre en ajoutant la vue en tant que diviseur à la liste list_item_layout de la vue recycleur .

        <View
            Android:id="@+id/view1"
            Android:layout_width="match_parent"
            Android:layout_height="1dp"
            Android:background="@color/colorAccent" />
3
vicky

La RecyclerView est un peu différente de la ListView. En fait, la RecyclerView a besoin d'une structure ListView semblable à celle-ci. Par exemple, un LinearLayout. La LinearLayout a des paramètres pour diviser chaque élément. Dans le code ci-dessous, j'ai un RecyclerView composé de CardView objets dans un LinearLayout avec un "remplissage" qui mettra un peu d'espace entre les éléments. Faites de cet espace vraiment petit et vous obtenez une ligne.

Voici la vue Recycler dans recyclerview_layout.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
    Android:layout_height="match_parent" Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    Android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".ToDoList">

    <!-- A RecyclerView with some commonly used attributes -->
    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/todo_recycler_view"
        Android:scrollbars="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"/>

</RelativeLayout>

Et voici à quoi chaque élément ressemble (et il apparaît divisé en raison d'Android: le remplissage dans le LinearLayout qui entoure tout.) Dans un autre fichier: cards_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical" Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    **Android:padding="@dimen/activity_vertical_margin"**>
    <!-- A CardView that contains a TextView -->
    <Android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/card_view"
        Android:layout_gravity="center"
        Android:layout_width="match_parent"
        Android:layout_height="100dp"
        Android:elevation="30dp"
        card_view:cardElevation="3dp">
            <TextView
                Android:id="@+id/info_text"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                />
    </Android.support.v7.widget.CardView>
</LinearLayout>
3
fiacobelli

Implémenter sa propre version de RecyclerView.ItemDecoration

public class SpacingItemDecoration extends RecyclerView.ItemDecoration {
    private int spacingPx;
    private boolean addStartSpacing;
    private boolean addEndSpacing;

    public SpacingItemDecoration(int spacingPx) {
        this(spacingPx, false, false);
    }

    public SpacingItemDecoration(int spacingPx, boolean addStartSpacing, boolean addEndSpacing) {
        this.spacingPx = spacingPx;
        this.addStartSpacing = addStartSpacing;
        this.addEndSpacing = addEndSpacing;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (spacingPx <= 0) {
            return;
        }

        if (addStartSpacing && parent.getChildLayoutPosition(view) < 1 || parent.getChildLayoutPosition(view) >= 1) {
            if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
                outRect.top = spacingPx;
            } else {
                outRect.left = spacingPx;
            }
        }

        if (addEndSpacing && parent.getChildAdapterPosition(view) == getTotalItemCount(parent) - 1) {
            if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
                outRect.bottom = spacingPx;
            } else {
                outRect.right = spacingPx;
            }
        }
    }

    private int getTotalItemCount(RecyclerView parent) {
        return parent.getAdapter().getItemCount();
    }

    private int getOrientation(RecyclerView parent) {
        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            return ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
        } else {
            throw new IllegalStateException("SpacingItemDecoration can only be used with a LinearLayoutManager.");
        }
    }
}
2
e.shishkin

PrimeAdapter

En utilisant PrimeAdapter , la gestion des séparateurs dans RecyclerViews pourrait être si simple. Il offre de multiples fonctionnalités et plus de flexibilité pour créer et gérer des séparateurs.

Vous pouvez créer un adaptateur comme suit: (Voir la documentation complète sur l’utilisation dans github )

val adapter = PrimeAdapter.with(recyclerView)
                    .setLayoutManager(LinearLayoutManager(activity))
                    .set()
                    .build(ActorAdapter::class.Java)

Après avoir créé une instance d'adaptateur, vous pouvez simplement ajouter un diviseur simplement en utilisant:

//----- default divider:
adapter.setDivider()

//----- divider with custom drawable:
adapter.setDivider(ContextCompat.getDrawable(context, R.drawable.divider))

//----- divider with custom color:
adapter.setDivider(Color.RED)

//----- divider with custom color and custom inset:
adapter.setDivider(Color.RED, insetLeft = 16, insetRight = 16)

//----- deactivate dividers:
adapter.setDivider(null)

enter image description here

1
aminography

Utilisez cette classe pour définir le séparateur dans votre RecyclerView.

 public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

        private int spanCount;
        private int spacing;
        private boolean includeEdge;

        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top Edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        }
    }
1
Makvin
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)); 
1
Amardeep

J'ai un moyen très simple d'ajouter un diviseur dans RecyclerView. Utilisez un adaptateur personnalisé pour modifier la disposition de la vue recycleur, puis ajoutez aux éléments de la vue recycleur LinearLayout avec une couleur d'arrière-plan (qui sera la couleur du séparateur) et ajoutez une hauteur de 1dp (ou selon vos besoins) et une largeur identique à celle du parent. .

Voici un exemple de code.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical" Android:layout_width="match_parent"
Android:layout_height="match_parent">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="horizontal"
    Android:padding="18dp">

    <TextView
        Android:id="@+id/list_row_SNO"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_weight=".8"
        Android:layout_gravity="end"
        Android:text="44."
        Android:textAlignment="center"
        Android:textSize="24sp"
        Android:textColor="@color/colorBlack"
        Android:fontFamily="sans-serif-condensed" />

    <TextView
        Android:id="@+id/list_row_Heading"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_weight=".2"
        Android:layout_gravity="start"
        Android:text="Student's application for leave and this what"
        Android:textAlignment="textStart"
        Android:textSize="24sp"
        Android:textColor="@color/colorBlack"
        Android:fontFamily="sans-serif-condensed" />

</LinearLayout>

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="1dp"
    Android:background="@color/colorHighlight">
</LinearLayout>
1
Nabajyoti Das

RecyclerView ne fournit pas une interface simple pour dessiner des séparateurs de listes. Mais en réalité, cela nous fournit un moyen beaucoup plus flexible d’établir des séparateurs. Nous utilisons RecyclerView.ItemDecoration pour décorer les carreaux de RecyclerView avec des diviseurs ou tout autre matériau de votre choix. C'est aussi pourquoi il s'appelle ItemDecoration.

Comme décrit dans Lignes directrices sur la conception du métal :

Le diviseur se situe dans la ligne de base de la tuile.

Ainsi, si vous souhaitez suivre les directives de conception de matériel, vous n'avez pas besoin d'espace supplémentaire pour dessiner les séparateurs. Il suffit de les dessiner sur les carreaux. Cependant, vous avez le droit de faire ce que vous voulez faire. J'ai donc mis en place un système qui vous permet de définir des incrustations et de dessiner sur/sous les carreaux.

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

Et vous pouvez l'utiliser comme ceci:

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

J'ai également écrit une application de démonstration sur la manière de mettre en œuvre ItemDecoration et de les utiliser. Vous pouvez consulter mon dépôt GitHub Dividers-For-RecyclerView . Il comporte trois implémentations:

  • UnderneathDivider
  • SuperpositionDivider
  • InsetDivider
1
Jiaheng

Voici mon approche paresseuse mais cela fonctionne: enveloppez le CardView dans une mise en page et définissez un remplissage/marge sur la mise en page parent pour imiter le séparateur, et forcez le diviseur normal à null

list_item.xml

<LinearLayout
    Android:id="@+id/entry_item_layout_container"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical"
    Android:paddingBottom="<divider_size>" > // this is the divider
    <CardView
        Android:layout_width="<width_size>"
        Android:layout_height="<height_size>">
        ...
    </CardView>
</LinearLayout

list.xml

<RecyclerView
 Android:divider="@null"
 Android:layout_width="<width_size>"
 Android:layout_height="<height_size>"
 ...
/>
0
kip2