RedEagle
RedEagle

Reputation: 2418

Margin/padding in last Child in RecyclerView

I'm trying to add Padding/Margin Bottom in the last row and Padding/Margin Top in the first row. I can not do it in the item xml as it would affect all of my Children.

I have headers and children in my RecyclerView Adapter so I can not use the

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

I need to use it individually on the last first row of each header

Upvotes: 174

Views: 94405

Answers (10)

ucMax
ucMax

Reputation: 5458

Long story short :

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

setClipToPadding Sets whether this list view will clip its children to its padding and resize (but not clip) any EdgeEffect to the padded region, if padding is present. (1)

Upvotes: 2

Radesh
Radesh

Reputation: 13565

I use this in kotlin to give bottom margin to last item only

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

Upvotes: 17

Matthew Mitchell
Matthew Mitchell

Reputation: 514

Java equivalent to @Radesh answer:

@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);
    }
}

Upvotes: 3

darshan patel
darshan patel

Reputation: 755

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

Add android:clipToPadding="false" and android:paddingBottom="100dp" in your recyclerview.

Upvotes: 72

Yogesh Shinde
Yogesh Shinde

Reputation: 393

Add android:clipToPadding="false" and android:paddingBottom="65dp" in your recyclerview. If you are using fab menu button and actions on recycler view cell.

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

Upvotes: 23

sourav pandit
sourav pandit

Reputation: 9115

I have modified amazing answer @snachmsm answer for better and give you idea how to use properly

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;
        }*/
    }
}

Upvotes: 2

snachmsm
snachmsm

Reputation: 19243

use 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;
        }
    }
}

and

//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));

Upvotes: 42

kassim
kassim

Reputation: 4009

For some reason the old clipToPadding=false solution isn't working for me. So I added an 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);
        }
    }
}

Upvotes: 5

Collins Abitekaniza
Collins Abitekaniza

Reputation: 4578

Instead of adding padding to both the top and bottom items, You can just add the padding to the top and bottom of your RecyclerView and set the clipToPadding attribute to 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" />

Upvotes: 119

C--
C--

Reputation: 16558

This issue is even easier to solve. You can apply necessary padding to the RecylerView itself and set clipToPadding to false, otherwise, the padding will chop off your scrolling area. Here is an example

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

See the padding will add 4dp on all sides including top and bottom. Then the clipToPadding parameter makes sure your child items are not chopped off. Now, add 4dp padding to all sides for your child items, and you are good to go. In total you get 8dp padding on sides and between items.

Upvotes: 324

Related Questions