Tutorial

Android GridLayoutManager Example

Published on August 4, 2022
author

Anupam Chugh

Android GridLayoutManager Example

Android GridLayoutManager is the RecyclerView.LayoutManager implementation to lay out items in a grid. In this tutorial, we’ll create an application that displays CardViews inside a RecyclerView in the form of a GridLayout. Also, we’ll implement an interface that makes RecyclerView item click similar to a ListView itemClickListener.

Android GridLayoutManager

We’ve implemented a RecyclerView using a LinearLayoutManager here. Now let’s use a GridLayoutManager to layout the RecyclerView as a grid. Following is the constructor for a GridLayoutManager.

GridLayoutManager (Context context, 
                int spanCount, 
                int orientation, 
                boolean reverseLayout)

reverseLayout if set true then layout items from end to start. To set the span size for each item, we invoke the method setSpanSizeLookup on the GridLayoutManager Let’s implement RecyclerView using a GridLayoutManager in a new Android Studio project.

Android GridLayoutManager Example Project Structure

Android GridLayoutManager example The project consists of a single Activity : MainActivity.java, an adapter class : RecyclerViewAdapter.java, a DataModel.java class and a custom GridLayoutManager class AutoFitGridLayoutManager.java. The xml layout of the MainActivity.java class is defined in the file activity_main.xml as

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </RelativeLayout>

</android.support.design.widget.CoordinatorLayout>

Note: Don’t forget to add the following dependencies for Material Design widgets and CardView in the build.gradle file.

compile 'com.android.support:cardview-v7:25.1.1'
compile 'com.android.support:design:25.1.1'

The DataModel.java class is given below: package com.journaldev.recyclerviewgridlayoutmanager;

public class DataModel {

    public String text;
    public int drawable;
    public String color;

    public DataModel(String t, int d, String c )
    {
        text=t;
        drawable=d;
        color=c;
    }
}

The DataModel class will hold the text, drawable icon and background colour of each item cell. The RecyclerViewAdapter.java class is given below:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;


public class RecyclerViewAdapter extends RecyclerView.Adapter {

    ArrayList mValues;
    Context mContext;
    protected ItemListener mListener;

    public RecyclerViewAdapter(Context context, ArrayList values, ItemListener itemListener) {

        mValues = values;
        mContext = context;
        mListener=itemListener;
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView textView;
        public ImageView imageView;
        public RelativeLayout relativeLayout;
        DataModel item;

        public ViewHolder(View v) {

            super(v);

            v.setOnClickListener(this);
            textView = (TextView) v.findViewById(R.id.textView);
            imageView = (ImageView) v.findViewById(R.id.imageView);
            relativeLayout = (RelativeLayout) v.findViewById(R.id.relativeLayout);

        }

        public void setData(DataModel item) {
            this.item = item;

            textView.setText(item.text);
            imageView.setImageResource(item.drawable);
            relativeLayout.setBackgroundColor(Color.parseColor(item.color));

        }


        @Override
        public void onClick(View view) {
            if (mListener != null) {
                mListener.onItemClick(item);
            }
        }
    }

    @Override
    public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_item, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder Vholder, int position) {
        Vholder.setData(mValues.get(position));

    }

    @Override
    public int getItemCount() {

        return mValues.size();
    }

    public interface ItemListener {
        void onItemClick(DataModel item);
    }
}

In the above code we’ve defined an ItemListener interface that’ll be implemented in the MainActivity.java class. The xml layout for each RecyclerView item is given below. recycler_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:card_view="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        card_view:cardCornerRadius="0dp"
        card_view:cardElevation="@dimen/margin10"
        card_view:cardMaxElevation="@dimen/margin10"
        card_view:contentPadding="@dimen/margin10">


        <RelativeLayout
            android:id="@+id/relativeLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_gravity="center">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:tint="@android:color/white"
                android:padding="5dp" />


            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:textColor="@android:color/white"
                android:layout_below="@+id/imageView" />


        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

The AutoFitGridLayoutManager.java class is given below:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;

public class AutoFitGridLayoutManager extends GridLayoutManager {

    private int columnWidth;
    private boolean columnWidthChanged = true;

    public AutoFitGridLayoutManager(Context context, int columnWidth) {
        super(context, 1);

        setColumnWidth(columnWidth);
    }

    public void setColumnWidth(int newColumnWidth) {
        if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
            columnWidth = newColumnWidth;
            columnWidthChanged = true;
        }
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (columnWidthChanged && columnWidth > 0) {
            int totalSpace;
            if (getOrientation() == VERTICAL) {
                totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
            } else {
                totalSpace = getHeight() - getPaddingTop() - getPaddingBottom();
            }
            int spanCount = Math.max(1, totalSpace / columnWidth);
            setSpanCount(spanCount);
            columnWidthChanged = false;
        }
        super.onLayoutChildren(recycler, state);
    }
}

The span count is dynamically calculated based on the orientation, width and height available. The MainActivity.java class is given below:

package com.journaldev.recyclerviewgridlayoutmanager;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.ItemListener {

    RecyclerView recyclerView;
    ArrayList arrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        arrayList = new ArrayList();
        arrayList.add(new DataModel("Item 1", R.drawable.battle, "#09A9FF"));
        arrayList.add(new DataModel("Item 2", R.drawable.beer, "#3E51B1"));
        arrayList.add(new DataModel("Item 3", R.drawable.ferrari, "#673BB7"));
        arrayList.add(new DataModel("Item 4", R.drawable.jetpack_joyride, "#4BAA50"));
        arrayList.add(new DataModel("Item 5", R.drawable.three_d, "#F94336"));
        arrayList.add(new DataModel("Item 6", R.drawable.terraria, "#0A9B88"));

        RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, arrayList, this);
        recyclerView.setAdapter(adapter);


        /**
         AutoFitGridLayoutManager that auto fits the cells by the column width defined.
         **/

        /*AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
        recyclerView.setLayoutManager(layoutManager);*/


        /**
         Simple GridLayoutManager that spans two columns
         **/
        GridLayoutManager manager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(manager);
    }

    @Override
    public void onItemClick(DataModel item) {

        Toast.makeText(getApplicationContext(), item.text + " is clicked", Toast.LENGTH_SHORT).show();

    }
}

  1. The above class implements the interface RecyclerViewAdapter.ItemListener and overrides the method onItemClick that’s defined in the adapter class. By doing this, we’ve implemented the RecyclerView Click Listener within our Activity instead of the Adapter class(similar to the standard onItemClickListener defined for a ListView)
  2. A DataModel class holds the details for each RecyclerView item
  3. The LayoutManager of the RecyclerView can be defined by either instantiating the AutoFitGridLayoutManager class with the column width set as 500 or by invoking the GridLayoutManager class object and setting the number of columns as 2

Let’s see the output of the application with the standard GridLayoutManager code. android GridLayoutManager grid layout output As you can see, each row has two items that span the column width in both orientations. Now comment out the code for simple GridLayoutManager and run the code for AutoFitGridLayoutManager

AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
recyclerView.setLayoutManager(layoutManager);

The output of the application in action is given below. android GridLayoutManager auto fit grid layout As you can see in the above output, when the orientation changes to landscape, each row has three items, thereby dynamically sizing the items to auto-fit the column width. This brings an end to this tutorial. You can download the final android GridLayoutManager project from the link given below.

Download Android GridLayoutManager Project

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Anupam Chugh

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
January 13, 2022

Thank you very much for your example!

- Peter

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    August 29, 2019

    Please what can you do to ensure that each item clicked opens a new activity? Thanks

    - Teddy Ben

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      May 10, 2019

      HI, My Adapter gives the error that i should implement the onBindViewHolder method. Can you help? Please.

      - Paulo Alexandre Neto Valentim

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        March 28, 2019

        The autofit grid is working for me . thanks for the help

        - wanfadger

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          February 19, 2019

          Thanks for the article! Especially for the AutoFitGridLayoutManager class

          - Kirill Karmazin

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            October 21, 2018

            How To open New Activity on click grid item

            - Vinod Prajapat

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              June 29, 2018

              It show the error: cannot find symbol method setData(Object) , So plz help me

              - Pooja Sehrawat

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                May 20, 2018

                Thanks for your post, it’s very useful I want to have this Grid items with different heights, can you explain how we can do this. As per the above code all card view items have equal heights, can you make all this are with own context heights, like flexible card items.

                - Naresh

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  November 13, 2017

                  thankxx for sharing code. this is very helpful for me.

                  - junaid khan

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    June 27, 2017

                    You should redo this tutorial - there are so many bad coding habits in it eg. your dataModel: don’t use t,d,c as parameters in a function signature!! use expressive names like what the really stand for like text, drawable and color - you can always use this.text = text in the body and keep your codestyle common over ALL files in this tutorial! the naming problem is quite huge in this tutorial: recycler_view_item.xml - the relativelayout is a button_wrapper, the drawable the button_icon the textview is the button text or something else… and be consistent about using hungarian notation - look at “say mNo” - by jake wharton If you do a tutorial like this - make it exceptionally good so that other people can learn Android in a good way. I don’t want to bash you - if you are doing something you gotta be doing it right!

                    - A Friend

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.