Margine / riempimento nell'ultimo figlio in RecyclerView


126

Sto cercando di aggiungere Padding / Margin Bottom nell'ultima riga e Padding / Margin Top nella prima riga. Non posso farlo nella voce xml poiché interesserebbe tutti i miei figli.

Ho intestazioni e figli nel mio adattatore RecyclerView quindi non posso usare il file

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

Devo usarlo individualmente sull'ultima prima riga di ogni intestazione


Usa in questo modo: <android.support.v7.widget.RecyclerView android: id = "@ + id / list" android: paddingBottom = "5dp" android: layout_width = "match_parent" android: layout_height = "wrap_content" />
Pankaj Arora

È possibile modificare la spaziatura interna e il margine in onBindViewHolder e quindi chiamare setIsRecyclable (false) sul titolare della visualizzazione
user3425867

Risposte:


9

Lo uso in 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

Questo problema è ancora più facile da risolvere. Puoi applicare il riempimento necessario allo RecylerViewstesso e impostarlo clipToPaddingsu false, altrimenti il ​​riempimento taglierà l'area di scorrimento. Ecco un esempio

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

Vedi l'imbottitura aggiungerà 4dp su tutti i lati, compresi quelli in alto e in basso. Quindi il parametro clipToPadding si assicura che gli elementi figlio non vengano tagliati. Ora, aggiungi 4dpimbottitura su tutti i lati per gli articoli del tuo bambino e sei a posto. In totale si ottiene un'imbottitura di 8dp sui lati e tra gli elementi.


Sì, è così che lo faccio di solito, ma io il mio RecyclerView è costituito da intestazioni e ogni intestazione ha i suoi figli, ecco perché devo impostarlo a livello di programmazione solo sull'ultima e prima riga di ogni intestazione
RedEagle

Non sono sicuro di aver capito. Come è correlato alle intestazioni all'interno di RecyclerView? Vuoi che le intestazioni non abbiano imbottitura? Anche in questo caso, puoi eliminare il riempimento sinistro e destro utilizzando la stessa soluzione.
Subin Sebastian

Ho intestazioni e ogni intestazione ha un conteggio non specifico di figli, quindi voglio aggiungere il padding / margine superiore e il primo figlio e il padding / margine inferiore all'ultimo figlio di ogni intestazione.
RedEagle

L'unica idea che avevo era impostare il margine superiore e inferiore nel layout della mia intestazione, ma mi chiedevo se esiste un modo più intelligente per
ottenerlo

In tal caso, puoi semplicemente aggiungere un elemento falso in RecyclerView dopo il tuo ultimo figlio. Questo è il modo più semplice, se non il più intelligente, per raggiungere questo obiettivo. :)
Subin Sebastian

82

Invece di aggiungere il riempimento agli elementi in alto e in basso, puoi semplicemente aggiungere il riempimento all'inizio e alla fine di RecyclerView e impostare l' clipToPaddingattributo su 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" />

Questa è la soluzione semplice, ma ho intestazioni e figli nel mio RecyclerView, quindi non posso usarlo
RedEagle

@ RedEagle Prova a vedere se ottieni l'effetto desiderato ma sono sicuro che funziona.
Collins Abitekaniza

1
Questa soluzione è migliore di quella per la decorazione dell'oggetto. Quando utilizzo ListAdapter e invio un elenco diverso, se l'ultimo elemento dell'elenco precedente non ha cambiato la sua posizione ma sono stati aggiunti nuovi elementi dopo di esso, il primo manterrà il riempimento inferiore anche se non è l'ultimo elemento dell'elenco. Di Più.
Ana Koridze

38

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

e

//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
Ehi, non sembra che RecyclerView.ItemDecoration ottenga più la classe di risorse, l'ho appena aggiunta come argomento nel costruttore.
Krtko

2
Soluzione Goog! Con supporto layout invertito: gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64

2
questa risposta deve essere votata! Sebbene la risposta di Subin Sebastian funzioni bene, tuttavia, con ItemDecoration gli spazi non sono uguali.
iroiroys

1
ma dopo aver inserito la rimozione degli elementi non ridisegnerà gli offset per tutti gli elementi
user924

può essere vero, poiché notifyItemInserted/ Removeddisegnerà solo un oggetto / rimuoverà l'oggetto e lo pulirà Viewlasciando intatti tutti gli altri bambini. ad esempio, quando un elemento è il primo nell'elenco (disegnato con il riempimento superiore) e ne stiamo aggiungendo uno nuovo all'inizio, allora l'elemento precedente-primo-attualmente-secondo sarà ancora riempito in cima ... la soluzione facile è chiamare notifyDataSetChanged(forza ridisegno tutti ...), più complessi necessitano di una logica per riconoscere notifyItemChanged(newPositionOfOldFirstAndOrLastItem)
quell'elemento

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" />

Aggiungi android:clipToPadding="false"e android:paddingBottom="100dp"nella tua revisione del riciclaggio.


2
Eccezionale! Perfetto
KevinB

16

Aggiungi android: clipToPadding = "false" e android: paddingBottom = "65dp" nel tuo recyclerview. Se stai usando il pulsante del menu favoloso e le azioni sulla cella di visualizzazione riciclatore.

<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

Per qualche motivo la vecchia clipToPadding=falsesoluzione non funziona per me. Quindi ho aggiunto una 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

Ho modificato la risposta sorprendente @snachmsm per meglio e ti do un'idea di come usarla correttamente

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;
        }*/
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.