Exemple de GridLayoutManager Android

Android GridLayoutManager est l’implémentation de RecyclerView.LayoutManager pour disposer des éléments dans une grille. Dans ce tutoriel, nous créerons une application qui affiche des CardViews à l’intérieur d’un RecyclerView sous la forme d’une GridLayout. De plus, nous implémenterons une interface qui rendra le clic sur un élément du RecyclerView similaire à un itemClickListener de ListView.

Android GridLayoutManager

Nous avons implémenté un RecyclerView en utilisant un LinearLayoutManager ici. Maintenant, utilisons un GridLayoutManager pour disposer le RecyclerView sous forme de grille. Voici le constructeur pour un GridLayoutManager.

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

Si reverseLayout est défini sur true, alors les éléments seront disposés de la fin vers le début. Pour définir la taille de span pour chaque élément, nous invoquons la méthode setSpanSizeLookup sur le GridLayoutManager. Implémentons un RecyclerView en utilisant un GridLayoutManager dans un nouveau projet Android Studio.

Exemple de structure de projet GridLayoutManager Android

Le projet se compose d’une seule activité : MainActivity.java, une classe adaptateur : RecyclerViewAdapter.java, une classe DataModel.java et une classe GridLayoutManager personnalisée AutoFitGridLayoutManager.java. La disposition xml de la classe MainActivity.java est définie dans le fichier activity_main.xml comme

<?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>

Remarque : N’oubliez pas d’ajouter les dépendances suivantes pour les widgets de Matériel Design et CardView dans le fichier build.gradle.

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

La classe DataModel.java est donnée ci-dessous : 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;
    }
}

La classe DataModel contiendra le texte, l’icône drawable et la couleur de fond de chaque cellule d’élément. La classe RecyclerViewAdapter.java est donnée ci-dessous :

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);
    }
}

Dans le code ci-dessus, nous avons défini une interface ItemListener qui sera implémentée dans la classe MainActivity.java. La disposition xml pour chaque élément RecyclerView est donnée ci-dessous. 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>

La classe AutoFitGridLayoutManager.java est donnée ci-dessous :

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);
    }
}

Le nombre de span est calculé dynamiquement en fonction de l’orientation, de la largeur et de la hauteur disponibles. La classe MainActivity.java est donnée ci-dessous :

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. La classe ci-dessus implémente l’interface RecyclerViewAdapter.ItemListener et surcharge la méthode onItemClick qui est définie dans la classe de l’adaptateur. En faisant cela, nous avons implémenté l’écouteur de clic RecyclerView dans notre Activité au lieu de la classe d’Adaptateur (similaire à l’onItemClickListener standard défini pour une ListView)
  2. A DataModel class holds the details for each RecyclerView item
  3. Le LayoutManager du RecyclerView peut être défini soit en instanciant la classe AutoFitGridLayoutManager avec la largeur de colonne définie à 500, soit en invoquant l’objet de classe GridLayoutManager et en définissant le nombre de colonnes à 2

Voyons le résultat de l’application avec le code standard GridLayoutManager. Comme vous pouvez le voir, chaque ligne a deux éléments qui s’étendent sur la largeur de la colonne dans les deux orientations. Maintenant, commentez le code pour le GridLayoutManager simple et exécutez le code pour AutoFitGridLayoutManager

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

La sortie de l’application en action est donnée ci-dessous. Comme vous pouvez le voir dans la sortie ci-dessus, lorsque l’orientation passe en mode paysage, chaque ligne contient trois éléments, ce qui permet de dimensionner dynamiquement les éléments pour qu’ils s’ajustent automatiquement à la largeur de la colonne. Cela marque la fin de ce tutoriel. Vous pouvez télécharger le projet final GridLayoutManager Android à partir du lien donné ci-dessous.

Télécharger le projet Android GridLayoutManager

Source:
https://www.digitalocean.com/community/tutorials/android-gridlayoutmanager-example