RecyclerView中最后一个孩子的边距/填充


126

我正在尝试在最后一行添加填充/边距底部,在第一行添加填充/边距顶部。我无法在xml项目中执行此操作,因为它会影响我所有的孩子。

我的RecyclerView适配器中有标题和子元素,因此我不能使用

   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(false)
user3425867 2015年

Answers:


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 ...
}

232

这个问题甚至更容易解决。您可以对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 2015年

不确定我是否理解。这与RecyclerView中的标头有什么关系?您是否希望标题没有填充?即使是这种情况,也可以使用相同的解决方案消除左右填充。
Subin Sebastian 2015年

我有标头,并且每个标头都有非特定数量的子代,因此我想在每个标头的最后一个子代中添加顶部填充/边距和第一个子对象以及底部填充/边距。
RedEagle 2015年

我唯一的想法是在页眉的布局中设置顶部和底部边距,但是我想知道是否有更智能的方法可以实现它
RedEagle 2015年

在这种情况下,您只需在您的最后一个孩子之后将一个假物品添加到RecyclerView中即可。这是最简单,甚至不是最明智的方法。:)
Subin Sebastian 2015年

82

您可以仅将RepaderView的顶部和底部添加填充并将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尝试看看您是否获得了预期的效果,但我确定它可以正常工作。
柯林斯Abitekaniza

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似乎不再获得资源类,我只是将其作为参数添加到构造函数中。
Krtko

2
Goog解决方案!具有反向布局支持:gist.github.com/Miha-x64/4e8754e72a1e65e3ca742744744ea501f16
Miha_x64

2
这个答案一定要赞成!尽管Subin Sebastian的答案很好,但是与ItemDecoration的空间并不相等。
iroiroys '17

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

在您的recyclerview中添加android:clipToPadding="false"android:paddingBottom="100dp"


2
太棒了!太完美了
KevinB

16

在您的recyclerview中添加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;
        }*/
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.