Skip to content

Instantly share code, notes, and snippets.

@cxyxlxdm
Last active April 19, 2024 08:43
Show Gist options
  • Star 86 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save cxyxlxdm/e57df3c3232ee446d464 to your computer and use it in GitHub Desktop.
Save cxyxlxdm/e57df3c3232ee446d464 to your computer and use it in GitHub Desktop.
Add column spacing in RecyclerView with GridLayoutManager

Android Recyclerview GridLayoutManager column spacing Here is the question, the first answer does not work well in my project,and it makes the spacing bigger between item and item. the second answer is quite perfect.But if RecyclerView has headers,it does not work well. Then I fixed it.

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Android Studio
 * User: Ailurus(ailurus@foxmail.com)
 * Date: 2015-10-28
 * Time: 15:20
 */
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;
    private int headerNum;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge, int headerNum) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
        this.headerNum = headerNum;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view) - headerNum; // item position

        if (position >= 0) {
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        } else {
            outRect.left = 0;
            outRect.right = 0;
            outRect.top = 0;
            outRect.bottom = 0;
        }
    }
    }
}

If you want to use it, just do as the following.

int spacingInPixels = getResources().getDimensionPixelSize(R.dimen.grid_layout_margin);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, spacingInPixels, true, 0));
@wogenhaosini
Copy link

Thank you very much。

@WMTAndroidJaymin
Copy link

Thanks...

@rgajadin
Copy link

rgajadin commented Jan 6, 2017

thanks

@eltray
Copy link

eltray commented Jan 25, 2017

Perfect! Thanks man.

@Fomovet
Copy link

Fomovet commented Jun 21, 2017

Thank you very much! You are my brother

@burakkarabonial
Copy link

Great, thanks!

@tatocaster
Copy link

just a converted into Kotlin

class GridSpacingItemDecoration(private val spanCount: Int, private val spacing: Int, private val includeEdge: Boolean, private val headerNum: Int) : RecyclerView.ItemDecoration() {

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
        val position = parent.getChildAdapterPosition(view) - headerNum // item position

        if (position >= 0) {
            val column = position % spanCount // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing
                }
                outRect.bottom = spacing // item bottom
            } else {
                outRect.left = column * spacing / spanCount // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing // item top
                }
            }
        } else {
            outRect.left = 0
            outRect.right = 0
            outRect.top = 0
            outRect.bottom = 0
        }
    }
}

@bubblexin
Copy link

Thanks.This is useful.

@naveedahmad99
Copy link

One Extra Brace remove from the end. Thanks

@ashishcors
Copy link

Awesome. Thanks

@vshkl
Copy link

vshkl commented Feb 14, 2021

In case GridLayoutManager has reversLayout param set to true this implementation will add extra vertical spacing to the bottommost row and omit it for the top one.
A small fix to address this:

class GridSpacingItemDecoration(
    private val spanCount: Int,
    private val spacing: Int,
    private val includeEdge: Boolean,
    private val headerNum: Int,
    private val isReverse: Boolean
) : RecyclerView.ItemDecoration() {

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val position = parent.getChildAdapterPosition(view) - headerNum

        if (position >= 0) {
            val column = position % spanCount

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount
                outRect.right = (column + 1) * spacing / spanCount

                if (position < spanCount) {
                    if (isReverse)
                        outRect.bottom = spacing else
                        outRect.top = spacing
                }

                if (isReverse)
                    outRect.top = spacing else
                    outRect.bottom = spacing
            } else {
                outRect.left = column * spacing / spanCount
                outRect.right = spacing - (column + 1) * spacing / spanCount

                if (position >= spanCount) {
                    if (isReverse)
                        outRect.bottom = spacing else
                        outRect.top = spacing
                }
            }
        } else {
            outRect.left = 0
            outRect.right = 0
            outRect.top = 0
            outRect.bottom = 0
        }
    }

}

@webserveis
Copy link

uhm headerNum usage, any sample?

@rahmatsyam
Copy link

Thanks, you save my day :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment