Centering items in a RecyclerView when it's implemented with GridLayoutManager

Micah Simmons picture Micah Simmons · Nov 17, 2015 · Viewed 7.7k times · Source

I have a RecyclerView implemented using the GridLayoutManager.

Depending on how many items are in the data set, the spanCount is between 1-4. The item widths change depending on the spanCount. If the spancount is 4 or above, the spanCount is left at 4.

If I have 5 items, this leaves 1 item left over (4 items in 1 row, 1 item left over), positioned at the left of the screen, on a row by itself. I would like it to be centered.

I have tried setting the left over item's margin's programatically, and wrapping both the recyclerView and individual items in LinearLayouts and setting the gravity to center, as well as setting the gravity of the recyclerView.

Example item XML:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal"

    >


    <RelativeLayout
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:id="@+id/relative"
        /> 

</LinearLayout>

Example RecyclerView XML

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="horizontal"
            >
           <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            />

        </LinearLayout>

Can anyone suggest a solution or, give me material to work from.

Thanks in advance.

Answer

Micah Simmons picture Micah Simmons · Nov 23, 2015

The answer to this is that, when you set the spancount of the GridLayoutManager, each item, no matter how big you try and make it, it will not expand in size beyond the dimensions permitted to the individual item. This permitted dimension 'boxes' in the item, and the size of the box is specified by the total height and width of the recyclerview in relation to, the spancount set on the GridLayoutManager. This also means you can't use gravity settings to push an item outside of it's 'box'.

The box/cell of the item is generally calculated like so: if the width of the recylerview is 100dp, and the spancount is 2, each items box/cell will have a width of the: width/spanCount. In this case, each box will have a width of 50dp (100dp/spanCountOf2).

In order for an item to take up the full 100dp, and then be centred in the space of 100dp, the item will have to take up 2 spancounts i.e. if the the width is 100dp, and spancount is 2, each item is allotted 50dp in width (1 of the 2 available spancount), for the item to take up the full 100dp, you need to tell the gridLayoutManager that the item at X position takes up 2 spanCounts instead of 1. Once the item takes up the full width, or the amount of spans you want it to take up, it can be centred or resized within its newly defined box (box size being width/height of the recycler in relation to its spancount).

To alter how many spans a given item takes up, call: setSpanSizeLookup() on the GridLayoutManager. Then identify the position of the item you want to alter the spanSize of and in the return statement of the setSpanSizeLookup() method, return how many spans you want it to use:

 gridlayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (position == 1) {
                        return 4; // the item in position now takes up 4 spans
                    }
                    return 1;
                }
            });
        }

By altering the spanCount of items, you can use gravity settings to centre an item in the middle of a row, if that item takes up the total spancount for every row.

Though, you may find you have to also use alternate layouts in the adapter for your items to centre items. So, potentiall, you might have to mix and match between settings different span counts and using different layouts via the getItemViewType() method in the recyclerAdapter.