Margin/padding in last Child in RecyclerView

AndroidAndroid RecyclerviewPadding

Android Problem Overview


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

Android Solutions


Solution 1 - Android

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.

Solution 2 - Android

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

Solution 3 - Android

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

Solution 4 - Android

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

Solution 5 - Android

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

Solution 6 - Android

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

Solution 7 - Android

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

Solution 8 - Android

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

Solution 9 - Android

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

Solution 10 - Android

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRedEagleView Question on Stackoverflow
Solution 1 - AndroidC--View Answer on Stackoverflow
Solution 2 - AndroidCollins AbitekanizaView Answer on Stackoverflow
Solution 3 - Androiddarshan patelView Answer on Stackoverflow
Solution 4 - AndroidsnachmsmView Answer on Stackoverflow
Solution 5 - AndroidYogesh ShindeView Answer on Stackoverflow
Solution 6 - AndroidRadeshView Answer on Stackoverflow
Solution 7 - AndroidkassimView Answer on Stackoverflow
Solution 8 - AndroidMatthew MitchellView Answer on Stackoverflow
Solution 9 - Androidsourav panditView Answer on Stackoverflow
Solution 10 - AndroiducMediaView Answer on Stackoverflow