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

938

Voici un exemple de la façon dont cela aurait pu être fait précédemment dans la ListViewclasse, en utilisant les paramètres divider 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 RecyclerViewclasse.

<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 correct de définir des marges et / ou d'ajouter une vue de séparation personnalisée directement dans la mise en page d'un élément de liste ou existe-t-il un meilleur moyen d'atteindre mon objectif?

Yeux
la source
Cela m'a aidé: stackoverflow.com/questions/26892296/…
Jared Burrows
@EyesClear Ajouter des éléments <TextView /> un autre xml et l'utiliser dans la liste Même activité.
Amitsharma
7
Il y a une classe dans le support lib com.homeretailgroup.argos.android.view.decorators.DividerItemDecorationet utilisez-la comme ça:mRecyclerView.addItemDecoration(new DividerItemDecoration(activity, LinearLayoutManager.VERTICAL));
fada21
Vous pouvez ajouter une marge inférieure à votre élément de liste pour les listes verticales et peut-être qu'il peut être utilisé comme séparateur?
resw67
La manière la plus simple consiste à ajouter des marges supérieure / inférieure autour du premier élément de la ligne de l'adaptateur. android: layout_marginBottom = "4dp". (Notez que l'ajout des marges à la disposition parent ne le coupera pas.)
pstorli

Réponses:

1228

Mise à jour d'octobre 2016

La version 25.0.0 d'Android Support Library a introduit la DividerItemDecorationclasse:

DividerItemDecoration est un RecyclerView.ItemDecoration qui peut être utilisé comme séparateur entre les éléments d'un LinearLayoutManager. Il soutient à la fois HORIZONTALet les VERTICALorientations.

Usage:

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

Réponse précédente

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


Contrairement à ListView, la RecyclerViewclasse n'a pas de paramètres liés au diviseur. , Vous avez besoin au lieu d'étendre ItemDecoration, une RecyclerViewclasse interne de »:

An ItemDecorationpermet à l'application d'ajouter un dessin spécial et un décalage de mise en page à des vues d'élément spécifiques de l'ensemble de données de l'adaptateur. Cela peut être utile pour dessiner des séparations entre les éléments, les reflets, les limites de regroupement visuel et plus encore.

Tous ItemDecorationssont attirés dans l'ordre où ils ont été ajoutés, avant que les vues de l' objet (dans onDraw()) et après les articles (en onDrawOver ( Canvas, RecyclerView, RecyclerView.State).

Vertical espacement ItemDecoration

Étendez ItemDecoration, ajoutez un constructeur personnalisé qui prend de l'espace heightcomme paramètre et remplacez la getItemOffsets()méthode:

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 outRect.top, outRect.leftet outRect.rightpropriétés pour effet désiré.

Séparateur ItemDecoration

Étendre ItemDecorationet remplacer la onDraw()méthode:

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 soit appeler le premier constructeur qui utilise les attributs du diviseur Android par défaut, ou le second qui utilise votre propre dessinable, 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 onDrawOver()plutôt la méthode.

Usage

Pour utiliser votre nouvelle classe, ajoutez VerticalSpaceItemDecorationou DividerSpaceItemDecorationà RecyclerView, par exemple dans la onCreateView()méthode 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 la bibliothèque de Lucas Rocha qui est censée simplifier le processus de décoration des objets. Je n'ai pas encore essayé.

Parmi ses caractéristiques :

  • Une collection de décorations d'articles en stock comprenant:
  • Espacement des articles Diviseurs horizontaux / verticaux.
  • Élément de liste
Yeux
la source
3
@droppin_science Corrigez-moi si je me trompe, mais je ne crée aucun objet dans onDraw(). Je fais simplement référence à des instances déjà existantes.
EyesClear
1
Je me demande si c'est une bonne idée d'utiliser Paint au lieu de créer un dessinable? Ensuite , je peux appeler canvas.drawLine(startX, startY, stopX, stopY, mPaint)à onDrawOver? Une différence de performance?
Arst
1
Juste un commentaire informatif: ajoutez toujours l'espace au dernier élément si vous prévoyez d'ajouter des éléments plus tard sur votre liste. Si vous ne le faites pas, lors de l'ajout d'un élément, il n'aura pas d'espace. Merci pour le VerticalSpace!
Tsuharesu
24
DividerItemDecoration comme indiqué ci-dessus ne fonctionnera pas si les articles sont complètement opaques, les séparateurs seront sur-utilisés par les articles. Dans ce cas, vous devez également remplacer getItemOffsets () et ajouter le décalage inférieur à outRect afin que le séparateur se retrouve en dehors de l'élément. Alternativement, vous pouvez remplacer onDrawOver () au lieu de onDraw () pour dessiner le séparateur après l'élément.
jpop
116
Une page entière de code pour simplement ajouter un séparateur à recyclerView est la meilleure réponse. Honte à toi, google.
prudent7j
480

Ajoutez simplement

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

Vous devrez peut-être également ajouter la dépendance
compile 'com.android.support:recyclerview-v7:27.1.0'

ÉDITER:

Pour le personnaliser un peu, vous pouvez ajouter un dessin personnalisé:

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

Vous êtes libre d'utiliser tout dessin personnalisé, 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>
Leo Droidcoder
la source
L'activité n'est pas nécessaire. Le contexte suffit
mac229
Ce doit être la bonne réponse. Plz, changez getActivity Pour juste contextualiser.
Jhon Fredy Trujillo Ortega
Il est également préférable d'obtenir l'orientation de votre LayoutManager.
lsrom
Je vous remercie! Vous pouvez également utiliser Configurationpour le diviseur vertical:if (orientation == Configuration.ORIENTATION_LANDSCAPE) { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL)); } else { recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));}
AlexS
3
Belle réponse, mais elle ajoute également un séparateur après le dernier élément.
CoolMind
256

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 d'exemple DividerItemDecoration.java "tiré directement des démos de support". ( Https://plus.google.com/103498612790395592106/posts/VVEB3m7NkSS )

J'ai pu obtenir des lignes de séparation bien après avoir importé ce fichier dans mon projet et l'ajouter comme décoration d'élément à la vue du recycleur.

Voici à quoi ressemble mon onCreateView dans mon fragment contenant le 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 qu'un style supplémentaire peut être fait, mais c'est un point de départ. :)

Duy Nguyen
la source
Comment ajoutez-vous les remplacer: "footerDividersEnabled", "headerDividersEnabled", "listSelector", "fastScrollEnabled", "smoothScrollbar", "textFilterEnabled"?
développeur Android
Des entrées sur Comment mettre le style?
nizam.sp
pour styliser cette solution, vous devez remplacer l'attribut "android: listDivider" dans votre thème
Pavel Dudka
1
Divider ne fonctionne pas avec RecyclerView. Vous devez utiliser RecyclerView.itemDecoration. Voir cette réponse: stackoverflow.com/a/27664023/2311451
Cocorico
3
pourquoi le séparateur étend-il toute la largeur de l'article? comment afficher comme dans les spécifications google.com/design/spec/components/lists.html#lists-specs
puce
156

Implémentation simple ItemDecorationpour 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;
        }
    }
}
SergeyA
la source
je reçois l'espace mais comment puis-je obtenir un diviseur
Pankaj Nimgade
26
getChildPositionest désormais obsolète, getChildAdapterPositionpeut être utilisé à la place.
EyesClear
4
N'oubliez pas (comme je l'ai fait) de supprimer l'appel à super.getItemOffsets, sinon vos décalages seront écrasés.
jayeffkay
@EyesClear ne devrait-il pas getChildLayoutPositionêtre utilisé?
Avinash R
3
cela met-il en œuvre l'espacement en pixels?
filthy_wizard
108

La plus simple consiste à définir la couleur d'arrière-plan pour RecyclerView et une couleur d'arrière-plan différente pour les articles. 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 (cela peut être n'importe quoi) avec une 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 ...

entrez la description de l'image ici

Madan Sapkota
la source
2
Quel tour! n'a besoin que de garder la liste blanche pendant le chargement.
Hamzeh Soboh
36
Attention au surmenage!
shem
@shem pourriez-vous élaborer?
RominaV
7
Lorsque vous dessinez dans un couple de couches Android l'une au-dessus de l'autre (l'arrière-plan de l'activité, l'arrière-plan de la vue de recyclage et l'arrière-plan de la vue de l'élément) - Android les dessine tous, également ceux qui ne sont pas visibles pour les utilisateurs. Cela s'appelait overdraw et pourrait affecter vos performances, en savoir plus ici: youtube.com/watch?v=T52v50r-JfE
shem
41

Je pense que l'utilisation d'un simple séparateur vous aidera

à ajouter un séparateur à chaque élément:
1- Ajoutez ceci au 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 la 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 articles, 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>
Belal mazlom
la source
Comment puis-je le faire fonctionner pour GridLayoutManager, pour afficher également des séparateurs verticaux entre les cellules?
développeur Android
2
resources.getDrawable () est désormais obsolète. Vous pouvez passer dans le contexte et utiliser ContextCompat.getDrawable (context, R.drawable.line_divider)
Eric B.
36

Comme je l'ai fixé ItemAnimators. leItemDecorator ne tombiez pas ou sortie , ainsi que l'animation.

J'ai simplement fini par avoir une ligne de vue dans mon fichier de disposition de vue d'élément de chaque élément. Cela a résolu mon cas. DividerItemDecorationsenti 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"/>
Javanator
la source
Tu as raison. Les animations ne fonctionnent pas avec ItemDecoration. Je ne sais pas pourquoi, mais sans que je spécifie quoi que ce soit, je reçois des animations et je trouve très distrayant et laid que les lignes créées par ItemDecoration ne suivent pas. Je vais donc utiliser une solution comme la vôtre.
Michel
Comment avez-vous traité le dernier élément?
agesgod
@oldergod. Vous avez montré le bon point de douleur. Je serais d'abord d'accord pour qu'un design ait également un diviseur sur le dernier article. Mais si tu ne veux pas ça. attribuez un identifiant à cette vue et masquez-la dans bindView si la position est la dernière.
Javanator du
@Javanator Je vois bien, la même approche que j'ai adoptée. Merci.
agesgod
le plus simple est le meilleur
hyyou2010
27

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 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:height="1dp" />
    <solid android:color="@android:color/black" />
</shape>
Faheem
la source
21

Puisqu'il n'y a pas de bonne façon de l'implémenter correctement en utilisant Material Design, je viens de faire l'astuce suivante pour ajouter directement un séparateur sur l'élément de liste:

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/dividerColor"/>
Yoann Hercouet
la source
DividerItemDecoration cesse de fonctionner après avoir eu quelques informations d'élévation de la conception du matériau (pour obtenir le même effet que dans la boîte de réception); c'est devenu trop compliqué pour une chose simple. Cette solution est simple et fonctionne.
DenisGL
21

La façon dont je gère la vue Divider et également les insertions Divider consiste à ajouter une extension RecyclerView.

1.

Ajoutez un nouveau fichier d'extension en nommant View ou RecyclerView:

RecyclerViewExtension.kt

et ajoutez la setDividerméthode d'extension dans le fichier RecyclerViewExtension.kt.

/*
* RecyclerViewExtension.kt
* */
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView


fun RecyclerView.setDivider(@DrawableRes drawableRes: Int) {
    val divider = DividerItemDecoration(
        this.context,
        DividerItemDecoration.VERTICAL
    )
    val drawable = ContextCompat.getDrawable(
        this.context,
        drawableRes
    )
    drawable?.let {
        divider.setDrawable(it)
        addItemDecoration(divider)
    }
}

2.

Créez un fichier de ressources Drawable à l'intérieur du drawablepackage comme recycler_view_divider.xml:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="10dp"
    android:insetRight="10dp">

    <shape>
        <size android:height="0.5dp" />
        <solid android:color="@android:color/darker_gray" />
    </shape>

</inset>

où vous pouvez spécifier la marge gauche et droite sur android:insetLeftet android:insetRight.

3.

Sur votre activité ou fragment où le RecyclerView est initialisé, vous pouvez définir le dessin personnalisé en appelant:

recyclerView.setDivider(R.drawable.recycler_view_divider)

4.

Vive 🍺

Rangée RecyclerView avec séparateur.

Gent Berani
la source
16

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

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

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

Où se divider_10dptrouve une ressource tirable 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>
Praveen Singh
la source
11

Pour ceux qui recherchent juste des espaces entre les articles dans le RecyclerViewvoir mon approche où vous obtenez des espaces égaux entre tous les articles, sauf dans le premier et le dernier articles où j'ai donné un plus grand rembourrage. J'applique uniquement le rembourrage à gauche / droite en horizontal LayoutManageret en haut / bas en vertical 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>
Ryan Amaral
la source
11

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

android:layout_marginTop="10dp"

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

Quantum Mattter
la source
3
Bien que cela fonctionne, ce n'est pas la bonne réponse, par exemple, car cela ne résout pas le problème sans faire des choses supplémentaires sur la disposition des lignes.En outre, en haut, la marge x1 apparaîtra, entre les lignes, la marge x2 apparaîtra.
Sreekanth Karumanaghat
Ce n'est pas une bonne idée car l' overscrolleffet lors du tirage à la fin de la liste aura un remplissage inutile qui lui sera appliqué lors du remplissageRecyclerView
AeroEchelon
Il est préférable d'envelopper la mise en page de l'élément dans une bibliothèque de support CardView afin que vous puissiez contrôler d'autres attributs, par exemple l'élévation / l'ombre, etc.: <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" card_view:cardElevation="4dp" <!-- your item's XML here --> </android.support.v7.widget.CardView>
kip2
11
  • Voici un hack simple pour ajouter un séparateur
  • Ajoutez simplement un arrière-plan à la disposition de votre article de recyclage 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éer le shape_border.xml suivant dans le dossier dessinable

  <?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.

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

turbandroïde
la source
1
Ce n'est pas une approche privilégiée. Bien que les initiés réponse @EyesClear INT dans le onDraw et parent.getChildAdapterPosition(view) != parent.getAdapter().getItemCount() - 1devrait probablement parent.getChildAdapterPosition(view) > 0avec de outRect.bottom = mVerticalSpaceHeightplus en plus , outRect.top = mVerticalSpaceHeightil devrait être la réponse acceptée.
droppin_science
@droppin_science - Vous ne pouvez pas le négliger en disant simplement que ce n'est pas une approche préférée, cela me donne des résultats précis comme prévu, je regarde également la réponse d'EyesClear mais cette réponse est trop compliquée pour un simple diviseur, cependant s'il y a besoin de faire une décoration supplémentaire avec l'article alors cela peut être la réponse acceptée.
turbandroid
Pour les votants, cette réponse a été donnée au moment où il n'y avait pas de cours officiel pour DividerItemDecoration, alors il suffit de comparer l'écart de temps entre cette réponse et la réponse suivante donnée par Leo Droidcoder. :)
turbandroid
9

J'ai bifurqué le DividerItemDecoration à partir d'un ancien contenu et l'ai simplifié pour l'adapter à mon cas d'utilisation, et je l'ai également modifié pour dessiner les séparateurs comme ils sont dessinés dans ListView, y compris un séparateur après le dernier élément de la liste. Cela 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()));
Apprenez OpenGL ES
la source
Correct, il est destiné à un LinearLayoutManager. Vous pouvez prendre l'idée derrière cela pour l'adapter à un GridLayoutManager.
Apprenez OpenGL ES
8

Au lieu de créer un shape xmlpour changer la hauteur et la couleur du séparateur. Vous pouvez créer par programmation 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)
Phan Van Linh
la source
c'est une réponse utile
taha
7

Tiré d'une recherche google, ajoutez cet articleDécoration à 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.");
    }
}
}
gatlingxyz
la source
Cela ne fonctionne bien que pour LinearLayoutManager. Que faut-il faire pour GridLayoutManager?
développeur Android
6

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));
Micro
la source
1
Cela fonctionne bien, mais il ne montre pas le séparateur sous le dernier élément de la liste. J'ai besoin comme ceci: mShowFirstDivider = false, mShowLastDivider = truemais ça ne marchera pas. Une idée pourquoi?
2015
Cela ne peut pas bien gérer GridLayoutManager.
développeur Android
6

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

Utilisez simplement ce qui suit ... extrait de la réponse d' 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);
    }
}

} puis utilisez ce qui précède comme suit

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

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

entrez la description de l'image ici

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

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

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

Veuillez me faire part de vos doutes dans les commentaires ci-dessous :)

Anudeep Samaiya
la source
1
Cela ne montre pas à quoi DividerItemDecorationressemble le code.
IgorGanapolsky
1
C'est une classe AOSP, j'ai trouvé le code pour vous ..... gist.githubusercontent.com/alexfu/0f464fc3742f134ccd1e/raw/…
Anudeep Samaiya
Cela ne fonctionne pas bien: il ne gère pas les lignes de différentes hauteurs et il n'affiche pas de séparateur vertical pour les grilles
développeur Android
5

Trop tard mais pour GridLayoutManagermoi 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 nombre de travées que vous avez.

Ollie.

Ollie Strevel
la source
À propos de l'espace supérieur, comment le modifieriez-vous pour qu'il prenne également en charge FlexboxLayoutManager?
développeur Android
5

Vous pouvez ajouter facilement par programmation.

Si votre Layout Manager 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 HORIZONTALES et VERTICALES.

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

la source

Beyaz
la source
5

J'ai l'impression qu'il y a un besoin d'une réponse simple, basée sur du 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);
Boober Bunz
la source
4

Si vous souhaitez ajouter le même espace pour les éléments, le moyen le plus simple consiste à ajouter un rembourrage 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"
/>
limitium
la source
4

J'ai ajouté une ligne dans l'élément de liste comme ci-dessous

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

1px dessinera la ligne mince.

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

Raja Peela
la source
1
Je préfère celui-ci, les autres sont trop compliqués.
Sam Chen
3

Le RecyclerViewest un peu différent du ListView. En fait, il a RecyclerViewbesoin d'une ListViewstructure similaire. Par exemple, a LinearLayout. A LinearLayoutdes paramètres pour diviser chaque élément. Dans le code ci-dessous, j'ai un RecyclerViewcomposé d' CardViewobjets dans unLinearLayout avec un "rembourrage" qui mettra un peu d'espace entre les éléments. Faites 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 ressemble chaque élément (et il apparaît divisé en raison de l'androïde: 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>
fiacobelli
la source
3

Une solution vraiment simple consiste à utiliser RecyclerView-FlexibleDivider

Ajouter une dépendance:

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

Ajoutez à votre vue de recyclage:

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

Et tu as fini!

Cristan
la source
fonctionne comme un charme ... je dois aimer le partage open-source.
Billy
3

1.L'un des moyens consiste à utiliser ensemble la vue de la vue de la carte et du recycleur, nous pouvons facilement ajouter un effet comme un diviseur. ex. https://developer.android.com/training/material/lists-cards.html

2.et l'autre consiste à ajouter la vue en tant que diviseur à list_item_layout de la vue du recycleur .

        <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/colorAccent" />
Vicky
la source
3
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 de chaque élément (ou à gauche et à droite). Ensuite, vous pouvez le définir à 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);
    }
}
wizChen
la source