Optimal Layout Design with GridLayoutManager in Android

In the realm of Android development, efficient layout is a crucial factor for a user-friendly application. A popular method for displaying content in a grid view is by utilizing GridLayoutManager in conjunction with RecyclerView. In this tutorial, we will provide an overview of using GridLayoutManager and demonstrate how to implement a grid view in an Android application.

Project Structure

Before delving into the implementation, let’s take a look at the project structure. Our sample project consists of an Activity (MainActivity.java), an Adapter (RecyclerViewAdapter.java), a data model class (DataModel.java), and a custom GridLayoutManager class (AutoFitGridLayoutManager.java).

 // DataModel.java
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;
    }
}

// RecyclerViewAdapter.java
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 {

    private ArrayList mValues;
    private Context mContext;
    private 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 = v.findViewById(R.id.textView);
            imageView = v.findViewById(R.id.imageView);
            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 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 holder, int position) {
        holder.setData(mValues.get(position));
    }

    @Override
    public int getItemCount() {
        return mValues.size();
    }

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

The data model class DataModel holds the details for each element in the grid view. The adapter RecyclerViewAdapter binds the data to the RecyclerView and handles click events.

Custom GridLayoutManager Class

 // AutoFitGridLayoutManager.java
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 custom AutoFitGridLayoutManager class automatically calculates the number of columns based on the available width and the defined column width value.

Implementation

In MainActivity, the RecyclerView is initialized and populated with data. By implementing the RecyclerViewAdapter.ItemListener interface, click events can be handled directly in the activity, enhancing code modularity.

 // MainActivity.java
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 = 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);

        // Use Custom GridLayoutManager
        AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
        recyclerView.setLayoutManager(layoutManager);
    }

    @Override
    public void onItemClick(DataModel item) {
        Toast.makeText(getApplicationContext(), item.text + " is clicked", Toast.LENGTH_SHORT).show();
    }
}

MainActivity implements the RecyclerViewAdapter.ItemListener interface and handles click events directly. The RecyclerView is populated with data, and the custom AutoFitGridLayoutManager is used to dynamically adjust the grid view to the screen size.

Conclusion

GridLayoutManager is a powerful option for implementing a grid view in Android applications. By combining it with RecyclerView and a well-structured adapter, developers can create user-friendly applications that dynamically adapt to various screen sizes and orientations.

With this tutorial, you have gained a basic insight into using GridLayoutManager and can now begin implementing grid views in your own Android applications.

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in: