Add margins to divider in RecyclerView

32.8k views Asked by At

i am building an android app which is using RecyclerView. I want to add dividers to RecyclerView, which I did using this code:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

So far everything works fine. However, the divider is taking the size of full screen and I want to add margins to it. Is there any way that I can add margins to the divider using a method that will add some space to the rectangle drawn and not by creating a custom drawable shape with margins and add it to the RecyclerView?

9

There are 9 answers

1
SANJAY GUPTA On BEST ANSWER

Use this and customize according to your requirement.

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};

    private Drawable divider;

    /**
     * Default divider will be used
     */
    public DividerItemDecoration(Context context) {
        final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
        divider = styledAttributes.getDrawable(0);
        styledAttributes.recycle();
    }

    /**
     * Custom divider will be used
     */
    public DividerItemDecoration(Context context, int resId) {
        divider = ContextCompat.getDrawable(context, resId);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + divider.getIntrinsicHeight();

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }
}
2
Vivek Mishra On

You can create your own item decoration for recycler view. Here is code for the same.

public class SimpleItemDecorator extends RecyclerView.ItemDecoration {

    int space;
    boolean isHorizontalLayout;
    public SimpleItemDecorator(int space) {
        this.space = space;
    }

    public SimpleItemDecorator(int space, boolean isHorizontalLayout) {
        this.space = space;
        this.isHorizontalLayout = isHorizontalLayout;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if(isHorizontalLayout)
        {
            outRect.bottom=space;
            outRect.right=space;
            outRect.left=space;
            outRect.top=space;

        } else {
            outRect.bottom = space;
            if (parent.getChildAdapterPosition(view) == 0)
                outRect.top = space;
            else
                outRect.top = 0;

        }


    }
}

And to use it with your recyclerview you can do like this:

 recyclerView.addItemDecoration(new SimpleItemDecorator(5));
1
Hamburg is nice On

Elaborating on @SeptimusX75: if you (like me) prefer to do UI stuff in XML you can create an inset drawable file. You'll have to create a second XML file but since in return your code gets cleaner I say it's worth it :-).

[UPDATE] as user @Zhou Hongbo suggest in the comments, using only one XML file: divider.xml:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/divider_base"
    android:insetRight="20dp"
    android:insetLeft="20dp">

    <shape>
        <android:shape="rectangle">
        <size android:height="1dp" />
        <solid android:color="@color/dividerColor" />
    </shape>

</inset>

[OLD ANSWER]:

divider_base.xml (the actual divider):

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="1dp" />
    <solid android:color="@color/dividerColor" />
</shape>

divider.xml (the inset):

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/divider_base"
    android:insetRight="20dp"
    android:insetLeft="20dp">
</inset>
0
Rahul Raina On

Here is a simple Kotlin code snippet to implement ItemDecoration with RecyclerView:

 recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
                override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
                    outRect.left = 20    // Left Margin.
                    outRect.right = 20   // Right Margin.
                    outRect.top = 16     // Top Margin.
                    outRect.bottom = 16  // Bottom Margin.
                }
            })

Explantation:- In the above example code, we are adding margins to each item of RecyclerView from all four directions.

Happy Coding...

2
Duanniston Cardoso Cabral On

shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#E6E7F0" />
    <size android:height="1dp" />
</shape>

layer.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/shape"
        android:left="16dp"
        android:right="16dp" />

</layer-list>

Code

val itemDecoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
itemDecoration.setDrawable(resources.getDrawable(R.drawable.layer, null))
recyclerView.addItemDecoration(itemDecoration)
0
amorenew On

Same like @Vivek answer but in Kotlin and different params

class SimpleItemDecorator : RecyclerView.ItemDecoration {

    private var top_bottom: Int = 0
    private var left_right: Int = 0

    /**
     * @param top_bottom for top and bottom margin
     * @param left_right for left and right margin
     */
    constructor(top_bottom: Int, left_right: Int = 0) {
        this.top_bottom = top_bottom
        this.left_right = left_right
    }

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.bottom = top_bottom
        outRect.top = top_bottom
        outRect.right = left_right
        outRect.left = left_right
    }
}
8
SeptimusX75 On

I think the most straightforward solution is to use the setDrawable method on the Decoration object and pass it an inset drawable with the inset values you want for the margins. Like so:

int[] ATTRS = new int[]{android.R.attr.listDivider};

TypedArray a = context.obtainStyledAttributes(ATTRS);
Drawable divider = a.getDrawable(0);
int inset = getResources().getDimensionPixelSize(R.dimen.your_margin_value);
InsetDrawable insetDivider = new InsetDrawable(divider, inset, 0, inset, 0);
a.recycle();

DividerItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
itemDecoration.setDrawable(insetDivider);
recyclerView.addItemDecoration(itemDecoration);
0
Zhou Hongbo On

I found the best and simplest solution

<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:insetLeft="40dp"
       android:insetRight="40dp" >
    <shape>
        <size android:height="1dp"/>
        <solid android:color="@color/recyclerview_divider" />
    </shape>
</inset>

From: https://stackoverflow.com/a/40434249/5093308

0
Triaro On

Below is the code for divider in RecyclerView with left margin. Just paste the code in your OnCreate method of MainActivity.

class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;

    public SimpleDividerItemDecoration(Context context) {
        mDivider = context.getResources().getDrawable(R.drawable.divider);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = 250;
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
}
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(
            getApplicationContext()));

Since, the divider.xml file will be missing from your drawable folder so below is the code that you have to paste on the divider layout after creating it on drawable folder.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

  <size
    android:width="1dp"
    android:height="1dp" />

  <solid android:color="@color/divider" />

</shape>