O Android GridLayoutManager é a implementação de RecyclerView.LayoutManager
para organizar itens em uma grade. Neste tutorial, criaremos uma aplicação que exibe CardViews dentro de um RecyclerView no formato de um GridLayout. Além disso, implementaremos uma interface que torna o clique no item do RecyclerView semelhante a um ListView itemClickListener
.
Android GridLayoutManager
Implementamos um RecyclerView usando um LinearLayoutManager aqui. Agora, vamos usar um GridLayoutManager
para organizar o RecyclerView como uma grade. Abaixo está o construtor para um GridLayoutManager.
GridLayoutManager (Context context,
int spanCount,
int orientation,
boolean reverseLayout)
Se reverseLayout estiver definido como verdadeiro, os itens são organizados do final para o início. Para definir o tamanho da coluna para cada item, invocamos o método setSpanSizeLookup
no GridLayoutManager. Vamos implementar o RecyclerView usando um GridLayoutManager em um novo projeto no Android Studio.
Exemplo de Estrutura de Projeto GridLayoutManager Android
O projeto consiste em uma única atividade:
MainActivity.java
, uma classe de adaptador: RecyclerViewAdapter.java
, uma classe DataModel.java
e uma classe GridLayoutManager personalizada AutoFitGridLayoutManager.java
. O layout xml da classe MainActivity.java é definido no arquivo 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>
Nota: Não se esqueça de adicionar as seguintes dependências para widgets de Material Design e CardView
no arquivo build.gradle.
compile 'com.android.support:cardview-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
A classe DataModel.java
é dada abaixo: 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;
}
}
A classe DataModel armazenará o texto, ícone desenhável e cor de fundo de cada célula do item. A classe RecyclerViewAdapter.java é dada abaixo:
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);
}
}
No código acima, definimos uma interface ItemListener que será implementada na classe MainActivity.java. O layout xml para cada item RecyclerView é dado abaixo. 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>
A classe AutoFitGridLayoutManager.java é dada abaixo:
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);
}
}
O número de span é calculado dinamicamente com base na orientação, largura e altura disponíveis. A classe MainActivity.java
está apresentada abaixo:
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();
}
}
- Esta classe implementa a interface
RecyclerViewAdapter.ItemListener
e substitui o métodoonItemClick
definido na classe do adaptador. Ao fazer isso, implementamos o ouvinte de clique do RecyclerView dentro da nossa Activity em vez da classe do Adaptador (similar ao padrão onItemClickListener definido para um ListView) - A DataModel class holds the details for each RecyclerView item
- O LayoutManager do RecyclerView pode ser definido tanto instanciando a classe AutoFitGridLayoutManager com a largura da coluna configurada como 500, quanto invocando o objeto da classe GridLayoutManager e configurando o número de colunas como 2
Vamos ver a saída da aplicação com o código padrão do GridLayoutManager. Como você pode ver, cada linha tem dois itens que ocupam a largura da coluna em ambas as orientações. Agora, comente o código para o GridLayoutManager simples e execute o código para AutoFitGridLayoutManager
AutoFitGridLayoutManager layoutManager = new AutoFitGridLayoutManager(this, 500);
recyclerView.setLayoutManager(layoutManager);
A saída da aplicação em ação é apresentada abaixo. Como você pode ver na saída acima, quando a orientação muda para paisagem, cada linha tem três itens, ajustando dinamicamente os itens para se ajustarem automaticamente à largura da coluna. Isso encerra este tutorial. Você pode baixar o projeto final do Android GridLayoutManager a partir do link fornecido abaixo.
Source:
https://www.digitalocean.com/community/tutorials/android-gridlayoutmanager-example