Поля / прокладка в останньому дочірні в RecyclerView


126

Я намагаюсь додати Padding / Margin Bottom в останньому ряду та Padding / Margin Top у першому рядку. Я не можу зробити це в пункті xml, як це вплине на всі мої діти.

У моєму RecyclerView Adapter є заголовки та діти, тому я не можу користуватися цим

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

Мені потрібно використовувати його окремо в останньому першому рядку кожного заголовка


Використовуйте так: <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, а потім зателефонувати setIsRecyclable (помилково) на власнику подання
користувач3425867

Відповіді:


9

Я використовую це в котліні

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

Це питання ще простіше вирішити. Ви можете застосувати необхідні прокладки до RecylerViewсебе та встановити clipToPaddingзначення false, інакше прокладка відрізає вашу область прокрутки. Ось приклад

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

Дивіться, що прокладка додасть 4dp з усіх боків, включаючи верхню і нижню. Тоді параметр clipToPadding гарантує, що предмети вашої дитини не будуть порубані. Тепер додайте 4dpпрокладки з усіх боків для ваших дітей, і ви добре йдете. Загалом ви отримуєте 8dp прокладки з боків та між предметами.


Так, зазвичай я це роблю, але я мій RecyclerView складається із заголовків, і кожен заголовок має власні дочірні, тому мені потрібно його програмно встановити лише для останнього та першого ряду кожного заголовка
RedEagle

Не впевнений, що розумію. Як це пов’язано із заголовками всередині RecyclerView? Ви хочете, щоб у заголовках не було прокладки? Навіть якщо це так, ви можете позбутися лівої та правої накладки, використовуючи те саме рішення.
Субін Себастьян

У мене є заголовки, і кожен заголовок має неспецифічну кількість дітей, тому я хочу додати верхню підкладку / поле та першу дочірню частину та нижню підкладку / поле в останню дочірню частину кожного заголовка.
RedEagle

Єдина ідея, яку у мене було, було встановлено верхній і нижній запас у макеті мого заголовка, але мені було цікаво, чи є розумніший спосіб досягти цього
RedEagle

У такому випадку ви можете просто додати підроблений елемент у RecyclerView після останньої дитини. Це найпростіший, якщо не найрозумніший спосіб досягти цього. :)
Субін Себастьян

82

Замість того, щоб додавати прокладки як до верхнього, так і до нижнього, ви можете просто додати прокладку вгорі та внизу RecyclerView і встановити clipToPaddingатрибут 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" />

Це просте рішення, але у мене в заголовку RecyclerView є заголовки та діти, тому я не можу ним користуватися
RedEagle

@RedEagle Спробуйте і подивіться, чи отримаєте ви бажаний ефект, але я впевнений, що він працює.
Коллінз Абітеканіза

1
Це рішення краще, ніж предмет прикраси. Коли я використовую ListAdapter і подаю інший список, якщо останній елемент попереднього списку не змінив свого положення, але нові елементи були додані після нього, перший збереже нижню підкладку, навіть якщо це не останній елемент у списку більше.
Ана Корідзе

38

використання 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;
        }
    }
}

і

//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
Ей, це не схоже на RecyclerView.ItemDecoration отримати клас ресурсів більше, я просто додав його як аргумент у конструкторі.
Кртко

2
Гугл-рішення! З підтримкою зворотного макета: gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64

2
ця відповідь повинна бути схваленою! Хоча відповідь Субіна Себастьяна працює добре, однак з пробілами ItemDecoration не рівні.
iroiroys

1
але після вставки видалення елементів вона не перемальовує компенсації для всіх елементів
user924

може бути правдою, оскільки notifyItemInserted/ Removedнамалює лише один предмет / видалить предмет і очистить його, Viewзалишивши всіх інших дітей недоторканими. наприклад, коли якийсь елемент вперше у списку (намальований верхньою накладкою), і ми додаємо новий вгорі, тоді раніше перший-в даний час другий елемент все ще буде прокладений зверху ... легко виправити дзвінки notifyDataSetChanged(примусити перемалювати все ...), більш складна потрібна певна логіка, щоб розпізнати той предмет, який був на першій та / або останньої позиції, перемістився, а потім зателефонувавnotifyItemChanged(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"та android:paddingBottom="100dp"перегляньте переробник.


2
Дивовижно! Це ідеально
KevinB

16

Додайте android: clipToPadding = "false" та android: paddingBottom = "65dp" у вашому перегляді рециркулятора. Якщо ви використовуєте кнопку меню fab та дії на комірці перегляду рециркулятора.

<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

Чомусь старе clipToPadding=falseрішення не працює для мене. Тому я додав 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

Я змінив дивовижну відповідь @snachmsm для кращого і даю вам уявлення, як правильно користуватися

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;
        }*/
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.