Marge / remplissage dans le dernier enfant dans RecyclerView


126

J'essaie d'ajouter Padding / Margin Bottom dans la dernière ligne et Padding / Margin Top dans la première ligne. Je ne peux pas le faire dans l'élément xml car cela affecterait tous mes enfants.

J'ai des en-têtes et des enfants dans mon adaptateur RecyclerView, je ne peux donc pas utiliser le

   android:padding="4dp"
   android:clipToPadding="false"

Je dois l'utiliser individuellement sur la dernière première ligne de chaque en-tête


Utilisez comme ceci: <android.support.v7.widget.RecyclerView android: id = "@ + id / list" android: paddingBottom = "5dp" android: layout_width = "match_parent" android: layout_height = "wrap_content" />
Pankaj Arora

Vous pouvez modifier le remplissage et la marge dans onBindViewHolder, puis appeler setIsRecyclable (false) sur le support de vue
user3425867

Réponses:


9

J'utilise ça dans kotlin

override fun onBindViewHolder(holder: RecyclerView.ViewHolder(view), position: Int) {
    if (position == itemsList.lastIndex){
        val params = holder.itemView.layoutParams as FrameLayout.LayoutParams
        params.bottomMargin = 100
        holder.itemView.layoutParams = params
    }else{
        val params = holder.itemView.layoutParams as RecyclerView.LayoutParams
        params.bottomMargin = 0
        holder.itemView.layoutParams = params
    }
  //other codes ...
}

233

Ce problème est encore plus facile à résoudre. Vous pouvez appliquer le remplissage nécessaire à RecylerViewlui - même et définir clipToPaddingsur false, sinon, le remplissage coupera votre zone de défilement. Voici un exemple

<android.support.v7.widget.RecyclerView
    android:padding="4dp"
    android:clipToPadding="false"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Voir le rembourrage ajoutera 4dp sur tous les côtés, y compris le haut et le bas. Ensuite, le paramètre clipToPadding s'assure que vos éléments enfants ne sont pas coupés. Maintenant, ajoutez un 4dprembourrage de tous les côtés pour vos articles enfants, et vous êtes prêt à partir. Au total, vous obtenez un rembourrage de 8dp sur les côtés et entre les éléments.


Oui, c'est comme ça que je le fais habituellement, mais mon RecyclerView est composé d'en-têtes et chaque en-tête a ses propres enfants, c'est pourquoi je dois le définir par programme sur la dernière et la première ligne de chaque en-tête uniquement
RedEagle

Pas sûr que je comprenne. Comment cela est-il lié aux en-têtes à l'intérieur de RecyclerView? Voulez-vous que les en-têtes n'aient pas de remplissage? Même si tel est le cas, vous pouvez vous débarrasser du rembourrage gauche et droit en utilisant la même solution.
Subin Sebastian

J'ai des en-têtes et chaque en-tête a un nombre d'enfants non spécifique, je veux donc ajouter un rembourrage / marge supérieur et le premier enfant et un rembourrage / marge inférieur au dernier enfant de chaque en-tête.
RedEagle

La seule idée que j'avais était de définir une marge supérieure et inférieure dans la disposition de mon en-tête, mais je me demandais s'il y avait un moyen plus intelligent de le
réaliser

Dans ce cas, vous pouvez simplement ajouter un faux article dans le RecyclerView après votre dernier enfant. C'est le moyen le plus simple, sinon le plus intelligent, d'y parvenir. :)
Subin Sebastian

82

Au lieu d'ajouter un remplissage aux éléments du haut et du bas, vous pouvez simplement ajouter le remplissage en haut et en bas de votre RecyclerView et définir l' clipToPaddingattribut sur false.

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="8dp"
    android:paddingBottom="8dp" />

C'est la solution simple, mais j'ai des en-têtes et des enfants dans mon RecyclerView, donc je ne peux pas l'utiliser
RedEagle

@RedEagle Essayez de voir si vous obtenez l'effet souhaité, mais je suis sûr que cela fonctionne.
Collins Abitekaniza

1
Cette solution est meilleure que celle de la décoration d'objets. Lorsque j'utilise ListAdapter et que je soumets une liste différente, si le dernier élément de la liste précédente n'a pas changé sa position mais que de nouveaux éléments ont été ajoutés après lui, le premier conservera son remplissage inférieur même s'il ne s'agit pas du dernier élément de la liste. plus.
Ana Koridze

38

utiliser ItemDecoration:

private 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) {
        int position = parent.getChildAdapterPosition(view);
        boolean isLast = position == state.getItemCount()-1;
        if(isLast){
            outRect.bottom = space;
            outRect.top = 0; //don't forget about recycling...
        }
        if(position == 0){
            outRect.top = space;
            // don't recycle bottom if first item is also last
            // should keep bottom padding set above
            if(!isLast)
                outRect.bottom = 0;
        }
    }
}

et

//8dp as px
int space = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
            getResources().getDisplayMetrics()); // calculated
//int space = getResources().getDimensionPixelSize(
//    R.dimen.list_item_padding_vertical); // from resources
recyclerView.addItemDecoration(new SpacesItemDecoration(space));

1
Hé, il ne semble pas que RecyclerView.ItemDecoration récupère plus la classe de ressources, je viens de l'ajouter comme argument dans le constructeur.
Krtko

2
Solution goog! Avec prise en charge de la mise en page inversée: gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64

2
cette réponse doit être votée pour! Bien que la réponse de Subin Sebastian fonctionne bien, cependant, avec ItemDecoration, les espaces ne sont pas égaux.
iroiroys

1
mais après avoir inséré des éléments supprimés, il ne redessine pas les décalages pour tous les éléments
user924

peut être vrai, car notifyItemInserted/ Removeddessinera un seul élément / supprimera l'élément et nettoiera tout en Viewlaissant tous les autres enfants intacts. Par exemple, lorsqu'un élément est le premier sur la liste (dessiné avec un rembourrage supérieur) et que nous en ajoutons un nouveau en haut, alors l'élément précédemment premier-actuellement-deuxième sera toujours rempli en haut ... une solution facile est d'appeler notifyDataSetChanged(forcer le redessiner all ...), plus complexe nécessite une logique pour reconnaître cet élément, qui était en première et / ou dernière position, déplacé puis appelnotifyItemChanged(newPositionOfOldFirstAndOrLastItem)
snachmsm

28
<android.support.v7.widget.RecyclerView
    android:id="@+id/rv_tpf"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipToPadding="false"
    android:paddingBottom="100dp" />

Ajoutez android:clipToPadding="false"et android:paddingBottom="100dp"dans votre vue de recyclage.


2
Impressionnant! C'est parfait
KevinB

16

Ajoutez android: clipToPadding = "false" et android: paddingBottom = "65dp" dans votre vue de recyclage. Si vous utilisez le bouton de menu fab et les actions sur la cellule de vue du recycleur.

<androidx.recyclerview.widget.RecyclerView
      android:id="@+id/dinner_recycler_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:clipToPadding="false"
      android:paddingBottom="65dp"/>

3

Pour une raison quelconque, l'ancienne clipToPadding=falsesolution ne fonctionne pas pour moi. J'ai donc ajouté un ItemDecoration

https://gist.github.com/kassim/582888fa5960791264fc92bc41fb6bcf

public class BottomPaddingDecoration extends RecyclerView.ItemDecoration {
    private final int bottomPadding;

    public BottomPaddingDecoration(int bottomPadding) {
        this.bottomPadding = bottomPadding;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        if (position == parent.getAdapter().getItemCount() - 1) {
            outRect.set(0, 0, 0, bottomPadding);
        }
    }
}

1

J'ai modifié la réponse incroyable @snachmsm pour mieux et vous donner une idée de la façon de l'utiliser correctement

public class SpacesItemDecoration extends DividerItemDecoration {
    private int space;

    public SpacesItemDecoration(Context clContext,int oriantation,int space) {
        super(clContext,oriantation);
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect,view,parent,state);
        int position = parent.getChildAdapterPosition(view);
        boolean isLast = position == state.getItemCount()-1;
        if(isLast){
            outRect.bottom = space;
            outRect.top = 0; //don't forget about recycling...
        }
       /* if(position == 0){
            outRect.top = space;
            // don't recycle bottom if first item is also last
            // should keep bottom padding set above
            if(!isLast)
                outRect.bottom = 0;
        }*/
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.