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.