Android : afficher une liste d'éléments en mode grille avec un RecyclerView
Jusqu'à présent, dans cette série sur le RecyclerView, nous avons vu comment afficher des éléments verticalement avec un RecyclerView. Dans cet article, nous verrons qu'il est possible d'afficher une grille d'éléments en utilisant les techniques déjà connues.
Voici un exemple en image de ce que l'on souhaite faire dans une application de gestion de séries :
Pour rappel, cet article fait partie d'une série sur le composant RecyclerView d'Android :
- Android : Optimiser l'affichage de vos listes en utilisant un RecyclerView
- Ajouter des sticky headers sur vos RecyclerView
- Ajouter des en-têtes repliables (collapsible headers) sur vos RecyclerView
- Créer des RecyclerView horizontaux, les fameux "horizontal RecyclerView"
- Android : comment créer un RecyclerView infini / endless ?
- Cet article.
- Ajouter des swipes actions sur un RecyclerView vertical.
- Suspens.
Mise en place théorique
Pour afficher les éléments en grille, il suffit de suivre ces étapes :
- calculer le nombre de colonnes à afficher
- assigner un LayoutManager de type GridLayoutManager à votre RecyclerView
- créer et assigner une instance de GridLayoutManager.SpanSizeLookup à votre RecyclerView
Il n'y a donc même pas besoin de modifier votre adapter !
Calcul du nombre de colonnes
Le calcul du nombre de colonnes va dépendre de ce que vous souhaitez afficher et de la taille que vous donnez à chaque colonne. Dans mon cas, je vais souhaiter donner 110dp à chaque colonne et je part du principe que le RecyclerView aura toute la largeur de l'écran à sa disposition. Il faudra aussi tenir compte de la densité de pixels de l'écran pour convertir la valeur en pixel vers du dp.
var scale = Android.Content.Res.Resources.System.DisplayMetrics.Density; var equivalentInPx = (int)(110f * scale ); float screenWidthInPx = Android.Content.Res.Resources.System .DisplayMetrics.WidthPixels; var colNum = widthInPx / equivalentInPx; return (int)Math.Floor(colNum);
Assignation du GridLayoutManager
Une fois cette valeur disponible, on va pouvoir assigner le GridLayoutManager au RecyclerView. Celui-ci prend justement en paramètre de son constructeur le nombre de colonnes à utiliser (comme c'est étrange !).
_gridLayoutManager = new GridLayoutManager(Context, NbColonnes); _recyclerView.SetLayoutManager(_gridLayoutManager);
Calcul du nombre de colonnes assigné à une cellule
Toute cette logique passe au travers d'une classe dérivant de GridLayoutManager.SpanSizeLookup dont il faudra surcharger la méthode GetSpanSize. Le RecyclerView va l'appeler pour chaque position dans son adapter de données et il attend en retour le nombre de colonnes nécessaire pour afficher un élément.
Dans cette méthode, nous allons utiliser l'adapter (que nous demanderons dans le constructeur) pour obtenir le type de l'élément à la position donnée. Si c'est un en-tête, on donnera le nombre de colonnes complets sinon on retournera 1 pour afficher un élément classique sur une seule colonne.
internal class MonSpanSizeLookup : GridLayoutManager.SpanSizeLookup { private readonly MonAdapter _adapter; public MonSpanSizeLookup(MonAdapter adapter) { _adapter = adapter; } public override int GetSpanSize(int position) { if (_adapter == null) { return 1; } var itemType = _adapter.GetItemViewType(position); bool isHeader = itemType != MonRecyclerAdapter.ItemType; return isHeader ? HowMuchColumn : 1; } }
Finalement, il ne faut pas oublier de donner une instance de cette classe au GridLayoutManager qu'on a précédemment assigné sur le RecyclerView :
_gridLayoutManager .SetSpanSizeLookup(new MonSpanSizeLookup(_curAdapter));
Happy coding :)
Commentaires