RecyclerView'da son alt öğede kenar boşluğu / dolgu


126

Son satıra Padding / Margin Bottom ve ilk satıra Padding / Margin Top eklemeye çalışıyorum. Tüm Çocuklarımı etkileyeceği için xml öğesinde yapamıyorum.

RecyclerView Adaptörümde üstbilgilerim ve altbilgilerim var, bu yüzden kullanamıyorum

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

Her başlığın son ilk satırında ayrı ayrı kullanmam gerekiyor


Bunun gibi kullanın: <android.support.v7.widget.RecyclerView android: id = "@ + id / list" android: paddingBottom = "5dp" android: layout_width = "match_parent" android: layout_height = "wrap_content" />
Pankaj Arora

OnBindViewHolder'daki dolguyu ve kenar boşluğunu değiştirebilir ve ardından görünüm tutucusunda setIsRecyclable (false) 'ı
çağırabilirsiniz

Yanıtlar:


9

Bunu kotlin'de kullanıyorum

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

Bu sorunu çözmek daha da kolay. Gerekli dolguyu RecylerViewkendisine uygulayabilir ve clipToPaddingyanlış olarak ayarlayabilirsiniz , aksi takdirde dolgu kaydırma alanınızı keser. İşte bir örnek

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

Dolgunun üst ve alt dahil her tarafta 4dp ekleyeceğini görün. Daha sonra clipToPadding parametresi, alt öğelerinizin kesilmemesini sağlar. Şimdi, 4dpçocuk eşyalarınız için her tarafa dolgu ekleyin ve gitmeniz iyi olur. Toplamda, yanlarda ve öğeler arasında 8dp dolgu elde edersiniz.


Evet, genellikle böyle yaparım, ancak RecyclerView'um başlıklardan oluşuyor ve her başlığın kendi alt öğeleri var, bu yüzden programlı olarak her başlığın yalnızca son ve ilk satırına ayarlamam gerekiyor
RedEagle

Anladığımdan emin değilim. Bunun RecyclerView içindeki başlıklarla nasıl bir ilişkisi var? Başlıklarda dolgu olmamasını istiyor musunuz? Durum böyle olsa bile, aynı çözümü kullanarak sol ve sağ dolgudan kurtulabilirsiniz.
Subin Sebastian

Başlıklarım var ve her başlığın belirli olmayan çocuk sayısı var, bu nedenle her başlığın son alt öğesinde üst dolgu / kenar boşluğu ve ilk alt ve alt dolgu / kenar boşluğu eklemek istiyorum.
RedEagle

Sahip olduğum tek fikir, üst ve alt kenar boşluğunu başlığımın düzenine yerleştirmekti, ancak onu elde etmenin daha akıllı bir yolu olup olmadığını merak ediyordum
RedEagle

Bu durumda, son çocuğunuzdan sonra RecyclerView'a sahte bir öğe ekleyebilirsiniz. Bunu başarmanın en akıllı yolu değilse de en basit yolu budur. :)
Subin Sebastian

82

Hem üst hem de alt öğelere dolgu eklemek yerine, dolguyu RecyclerView'unuzun üst ve alt kısmına ekleyebilir ve clipToPaddingniteliği olarak ayarlayabilirsiniz 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" />

Bu kolay çözüm, ancak RecyclerView'umda başlıklarım ve alt
öğeleri var

@RedEagle İstediğiniz efekti alıp almadığınızı deneyin ve görün ama eminim işe yarıyor.
Collins Abitekaniza

1
Bu çözüm, Eşya Dekorasyonundan daha iyidir. ListAdapter kullandığımda ve farklı bir liste gönderdiğimde, önceki listenin son öğesi konumunu değiştirmediyse ancak ondan sonra yeni öğeler eklendiyse, listedeki son öğe olmasa bile eski alt dolgusunu koruyacaktır. Daha.
Ana Koridze

38

kullanım 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;
        }
    }
}

ve

//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
Hey, RecyclerView.ItemDecoration artık kaynak sınıfını alıyor gibi görünmüyor, ben sadece yapıcıya argüman olarak ekledim.
Krtko

2
Goog çözümü! Ters düzen desteği ile: gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64

2
bu cevap olumlu oylanmalı! Subin Sebastian'ın cevabı iyi çalışıyor olsa da ItemDecoration ile boşluklar eşit değil.
iroiroys

1
ancak öğeleri kaldırdıktan sonra, tüm öğeler için ofsetleri yeniden
çizmeyecek

olarak, doğru olabilir notifyItemInserted/ Removedyalnızca bir öğe / kaldır öğesini çizmek ve onu oluyor temizler Viewbakir diğer tüm çocuk herkesin bırakarak. Örneğin, listede bir öğe birinci olduğunda (üst dolguyla çizilir) ve üste yenisini eklediğimizde, daha önce birinci-şu anda-ikinci öğe yine de üstte doldurulur ... kolay düzeltme çağırmaktır notifyDataSetChanged(yeniden çizmeye zorla Hepsi ...), daha karmaşık, ilk ve / veya son konumda olan öğeyi tanımak için biraz mantığa ihtiyaç duyar, hareket eder ve sonra çağırırnotifyItemChanged(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" />

android:clipToPadding="false"Ve android:paddingBottom="100dp"geri dönüşümcü görünümünüze ekleyin .


2
Müthiş! Bu mükemmel
KevinB

16

Geri dönüşüm görünümünüze android: clipToPadding = "false" ve android: paddingBottom = "65dp" ekleyin. Fab menü düğmesini kullanıyorsanız ve geri dönüşümcü görüntüleme hücresindeki eylemler.

<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

Bazı nedenlerden dolayı eski clipToPadding=falseçözüm benim için çalışmıyor. Bu yüzden bir ItemDecoration ekledim

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

İnanılmaz cevabı @snachmsm cevabını daha iyi hale getirdim ve nasıl doğru kullanacağınız konusunda size fikir verdim

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;
        }*/
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.