Маржа / заполнение в последнем дочернем элементе в RecyclerView

126

Я пытаюсь добавить Padding / Margin Bottom в последнюю строку и Padding / Margin Top в первую строку. Я не могу сделать это в элементе xml, так как это повлияет на всех моих детей.

У меня есть заголовки и дочерние элементы в моем адаптере RecyclerView, поэтому я не могу использовать

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

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

RedEagle
источник
Используйте так: <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 (false) в держателе представления
user3425867

Ответы:

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 ...
}
Radesh
источник
234

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

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

Смотрите, что padding добавит 4dp со всех сторон, включая верх и низ. Затем параметр clipToPadding гарантирует, что ваши дочерние элементы не отрублены. Теперь добавьте 4dpотступы со всех сторон для ваших дочерних элементов, и все готово. Всего вы получите отступы 8dp по бокам и между элементами.

Субин Себастьян
источник
Да, я обычно так делаю, но мой RecyclerView состоит из заголовков, и каждый заголовок имеет свои собственные
дочерние элементы
Не уверен, что понимаю. Как это связано с заголовками внутри RecyclerView? Вы хотите, чтобы заголовки не имели заполнения? Даже если это так, вы можете избавиться от левого и правого отступов, используя одно и то же решение.
Субин Себастьян
У меня есть заголовки, и каждый заголовок имеет неспецифическое количество дочерних элементов, поэтому я хочу добавить верхнее заполнение / поле и первое дочернее и нижнее заполнение / поле в последнем дочернем элементе каждого заголовка.
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" />
Коллинз Абитеканиза
источник
Это простое решение, но у меня есть заголовки и
дочерние элементы
@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));
snachmsm
источник
1
Эй, похоже, RecyclerView.ItemDecoration больше не получает класс ресурса, я просто добавил его в качестве аргумента в конструктор.
Krtko
2
Решение Goog! С поддержкой обратного макета: gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744ea501f16
Miha_x64
2
за этот ответ нужно проголосовать! Хотя ответ Субина Себастьяна работает хорошо, однако с ItemDecoration пространства не равны.
iroiroys
1
но после вставки удаления элементов он не перерисовывает смещения для всех элементов
user924
может быть правдой, так как notifyItemInserted/ Removedбудет рисовать только один элемент / удалять элемент и очищать его, Viewоставляя все остальные дочерние элементы нетронутыми. например, когда какой-то элемент находится первым в списке (нарисованный с верхним заполнением), и мы добавляем новый в начало, тогда элемент «ранее первый-текущий-второй» все равно будет заполнен сверху ... простое решение - вызвать notifyDataSetChanged(принудительно перерисовать все ...), более сложным нужна некоторая логика для распознавания того элемента, который был на первой и / или последней позиции, перемещен, а затем notifyItemChanged(newPositionOfOldFirstAndOrLastItem)
вызван
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"в свой recyclerview.

Даршан Патель
источник
2
Потрясающие! Это идеально
KevinB
16

Добавьте android: clipToPadding = "false" и android: paddingBottom = "65dp" в ваш recyclerview. Если вы используете потрясающую кнопку меню и действия в ячейке просмотра ресайклера.

<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;
        }*/
    }
}
Сурав Пандит
источник