Margin/padding 最后 Child 在 RecyclerView 中

Margin/padding in last Child in RecyclerView

我正在尝试在最后一行添加 Padding/Margin 底部,在第一行添加 Padding/Margin 顶部。我不能在项目 xml 中这样做,因为它会影响我的所有 Children.

我的 RecyclerView 适配器中有 headers 和 children,所以我不能使用

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

我需要在每个 header

的最后第一行单独使用它

使用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));

您可以只将填充添加到 RecyclerView 的顶部和底部,并将 clipToPadding 属性设置为 false。[=13,而不是同时向顶部和底部项目添加填充。 =]

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="8dp"
    android:paddingBottom="8dp" />

这个问题更容易解决。您可以对 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 的填充。

出于某种原因,旧的 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);
        }
    }
}
<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"

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

我已经修改了惊人的答案@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;
        }*/
    }
}

在您的回收视图中添加 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"/>

Java 相当于@Radesh 回答:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    if (position == itemsList.size() - 1) {
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
        params.bottomMargin = 100;
        holder.itemView.setLayoutParams(params);
    } else {
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
        params.bottomMargin = 0;
        holder.itemView.setLayoutParams(params);
    }
}

长话短说:

    int freeSpaceAtBottom = 100; // the bottom free space in pixels
    myRecyclerView.setClipToPadding(false);
    myRecyclerView.setPadding(0,0,0,freeSpaceAtBottom);

setClipToPadding 设置此列表视图是否将其子项裁剪到其填充并调整(但不裁剪)任何 EdgeEffect 到填充区域,如果存在填充. (1)