MDC-102 Android: Structure et mise en page Material (Java)

1. Introduction

logo_components_color_2x_web_96dp.png

Material Components (MDC) aide les développeurs à implémenter Material Design. Conçu par une équipe d'ingénieurs et de spécialistes de l'expérience utilisateur chez Google, MDC propose des dizaines de composants d'interface utilisateur élégants et fonctionnels. Il est disponible pour Android, iOS, le Web et Flutter.material.io/develop.

Dans l'atelier de programmation MDC-101, vous avez utilisé deux composants Material Components (MDC) pour créer une page de connexion : des champs de texte et des boutons. Sur ces bases, enrichissons notre application en y ajoutant navigation, structure et données.

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez créer un écran d'accueil pour Shrine, une application d'e-commerce pour la vente de vêtements et d'articles pour la maison. Cet écran contiendra :

  • Une barre d'application supérieure
  • Une liste de produits sous forme de grille

249db074eff043f4.png

Composants MDC-Android utilisés dans cet atelier de programmation

  • AppBarLayout
  • MaterialCardView

Prérequis

  • Connaissances de base sur le développement Android
  • Android Studio (téléchargez-le ici si vous ne l'avez pas déjà fait)
  • Un émulateur ou un appareil Android (disponible via Android Studio)
  • L'exemple de code (voir l'étape suivante)

Comment évalueriez-vous votre niveau d'expérience en matière de création d'applications Android ?

Débutant Intermédiaire Expert

2. Configurer l'environnement de développement

Vous avez déjà suivi l'atelier MDC-101 ?

Si vous avez terminé l'atelier de programmation MDC-101, votre code devrait être prêt. Vous pouvez passer à l'étape 3: Ajouter une barre d'application supérieure.

Vous partez de zéro ?

Télécharger l'application de départ de l'atelier de programmation

L'application de départ se trouve dans le répertoire material-components-android-codelabs-102-starter/java. Assurez-vous d'accéder à ce répertoire avec la commande cd avant de commencer.

… ou cloner l'atelier depuis GitHub

Pour cloner cet atelier de programmation à partir de GitHub, exécutez les commandes suivantes :

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 102-starter

Charger le code de départ dans Android Studio

  1. Une fois l'assistant de configuration terminé et la fenêtre de bienvenue dans Android Studio affichée, cliquez sur Open an existing Android Studio project (Ouvrir un projet Android Studio existant). Accédez au répertoire dans lequel vous avez installé l'exemple de code, puis sélectionnez java -> shrine (ou recherchez shrine sur votre ordinateur) pour ouvrir le projet Shrine.
  2. Attendez qu'Android Studio crée et synchronise le projet (voir les indicateurs d'activité situés en bas de la fenêtre Android Studio).
  3. À ce stade, Android Studio peut générer des erreurs de compilation, car vous ne disposez pas du SDK Android ni de certains outils de compilation, comme celui présenté ci-dessous. Suivez les instructions fournies dans Android Studio pour installer/mettre à jour ces éléments et synchroniser votre projet.

F5H6srsw_5xOPGFpKrm1RwgewatxA_HUbDI1PWoQUAoJcT6DpfBOkAYwq3S-2vUHvweUaFgAmG7BtUKkGouUbhTwXQh53qec8tO5eVecdlo7QIoLc8rNxFEBb8l7RlS-KzBbZOzVhA

Ajouter des dépendances de projet

Le projet nécessite une dépendance à la bibliothèque de compatibilité Android MDC. Cette dépendance devrait déjà être listée dans l'exemple de code que vous avez téléchargé, mais il est recommandé de suivre les étapes ci-dessous pour vous en assurer.

  1. Accédez au fichier build.gradle du module app et vérifiez si le bloc dependencies inclut bien une dépendance à MDC Android :
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Facultatif) Si nécessaire, modifiez le fichier build.gradle pour ajouter les dépendances suivantes et synchroniser le projet.
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

Exécuter l'application de départ

  1. Assurez-vous que la configuration de compilation à gauche du bouton Run/Play (Exécuter/Lire) est app.
  2. Appuyez sur le bouton vert pour créer et exécuter l'application.
  3. Dans la fenêtre Select Deployment Target (Sélectionner une cible de déploiement), si un appareil Android figure déjà dans la liste des appareils disponibles, passez à l'étape 8. Sinon, cliquez sur Create New Virtual Device (Créer un appareil virtuel).
  4. Sur l'écran Select Hardware (Sélectionner le matériel), sélectionnez un appareil (par exemple, Pixel 2), puis cliquez sur Next (Suivant).
  5. Sur l'écran System Image (Image système), sélectionnez une version récente d'Android (de préférence le niveau d'API le plus élevé). Sinon, cliquez sur le lien Télécharger qui s'affiche, puis procédez au téléchargement.
  6. Cliquez sur Next (Suivant).
  7. Sur l'écran Android Virtual Device (AVD) (Appareil virtuel Android), laissez les paramètres tels quels et cliquez sur Finish (Terminer).
  8. Sélectionnez un appareil Android dans la boîte de dialogue de la cible de déploiement.
  9. Cliquez sur OK.
  10. Android Studio crée l'application, la déploie et l'ouvre automatiquement sur l'appareil cible.

Opération réussie. La page de connexion de Shrine créée dans l'atelier de programmation MDC-101 devrait s'afficher.

4cb0c218948144b4.png

Maintenant que l'écran de connexion semble correct, remplissons l'application avec quelques produits.

3. Ajouter une barre d'application supérieure

L'écran d'accueil s'affiche lorsque la page de connexion est ignorée, avec le message "Vous avez réussi !". Parfait ! Mais à présent, l'utilisateur n'a aucune action à effectuer et n'a aucune idée de sa position dans l'application. Pour vous aider, ajoutons la navigation.

Material Design propose des formats de navigation qui garantissent une grande facilité d'utilisation. La barre d'application supérieure est l'un des composants de navigation les plus notables.

Pour offrir aux utilisateurs un accès rapide à d'autres actions, ajoutons une barre d'application supérieure.

Ajouter un widget AppBar

Dans shr_product_grid_fragment.xml, supprimez la balise <LinearLayout> contenant le message "Vous l'avez fait !". TextView et remplacez-le par le code suivant :

shr_product_grid_fragment.xml

<com.google.android.material.appbar.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/app_bar"
       style="@style/Widget.Shrine.Toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>

Votre shr_product_grid_fragment.xml devrait se présenter comme suit:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

De nombreuses barres d'application comportent un bouton à côté du titre. Ajoutons une icône de menu à la nôtre.

Ajouter une icône de navigation

Toujours dans shr_product_grid_fragment.xml, ajoutez le code suivant au composant XML Toolbar (que vous venez d'ajouter à votre mise en page):

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

Votre shr_product_grid_fragment.xml doit se présenter comme suit :

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">
  
   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

Ajouter des boutons d'action et styliser la barre d'application supérieure

Vous pouvez également ajouter des boutons à l'extrémité de la barre d'application. Sous Android, ils sont appelés boutons d'action.

Nous allons appliquer un style à la barre d'application supérieure et ajouter des boutons d'action à son menu par programmation.

Commençons par créer une méthode pour configurer la barre d'outils. La méthode doit obtenir une référence à la barre d'outils à l'aide de son id, ainsi qu'une référence à l'activité à l'aide de getActivity(). Si l'activité n'est pas nulle, définissez Toolbar pour qu'il soit utilisé comme ActionBar à l'aide de setSupportActionBar:

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }
}

Ensuite, juste sous la méthode setUpToolbar que nous venons d'ajouter, remplaçons onCreateOptionsMenu pour gonfler le contenu de shr_toolbar_menu.xml dans la barre d'outils:

ProductGridFragment.java

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
   super.onCreateOptionsMenu(menu, menuInflater);
}

Ajoutez maintenant un appel à la méthode setUpToolbar que nous avons ajoutée au contenu de la méthode onCreateView() avec ce qui suit :

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   // Inflate the layout for this fragment with the ProductGrid theme
   View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

   // Set up the toolbar
   setUpToolbar(view);

   return view;
}

Enfin, ajoutez une méthode onCreate() à ProductGridFragment.java. Dans le corps de la méthode, définissez le paramètre de setHasOptionMenu sur true.

La méthode doit se présenter comme suit:

ProductGridFragment.java

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setHasOptionsMenu(true);
}

Le code ci-dessus définit la barre d'application de notre mise en page XML en tant que barre d'action pour cette activité. Le rappel onCreateOptionsMenu indique à l'activité ce qu'utiliser comme menu. Dans ce cas, les éléments de menu de R.menu.shr_toolbar_menu sont placés dans la barre d'application.

Le fichier de menu contient deux éléments : "Rechercher" et "Filtrer".

shr_toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/search"
       android:icon="@drawable/shr_search"
       android:title="@string/shr_search_title"
       app:showAsAction="always" />
   <item
       android:id="@+id/filter"
       android:icon="@drawable/shr_filter"
       android:title="@string/shr_filter_title"
       app:showAsAction="always" />
</menu>

Une fois ces modifications effectuées, votre fichier ProductGridFragment.java devrait se présenter comme suit:

ProductGridFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;


public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }
  
   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       return view;
   }
  
   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Compilez et exécutez. Votre écran d'accueil devrait se présenter ainsi :

d04e8aa3b27f4754.png

La barre d'outils a maintenant une icône de navigation, un titre et deux icônes d'action sur le côté droit. La barre d'outils présente également un effet d'élévation dû à un léger ombrage indiquant qu'elle se trouve à un niveau différent de celui du contenu.

4. Ajouter une carte

Maintenant que notre application est un peu plus structurée, organisons ses contenus en les plaçant dans des fiches.

Ajouter une carte

Commençons par ajouter une fiche sous la barre d'application supérieure. Une fiche doit comporter une zone pour une image, un titre et un libellé pour le texte secondaire.

Dans shr_product_grid_fragment.xml , ajoutez ce qui suit sous AppBarLayout:

shr_product_grid_fragment.xml

<com.google.android.material.card.MaterialCardView
   android:layout_width="160dp"
   android:layout_height="180dp"
   android:layout_marginBottom="16dp"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"
   android:layout_marginTop="70dp"
   app:cardBackgroundColor="?attr/colorPrimaryDark"
   app:cardCornerRadius="4dp">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:background="#FFFFFF"
       android:orientation="vertical"
       android:padding="8dp">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_title"
           android:textAppearance="?attr/textAppearanceHeadline6" />

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_description"
           android:textAppearance="?attr/textAppearanceBody2" />
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Compilez et exécutez:

f6184a55ccb5f920.png

Dans cet aperçu, vous pouvez voir que la carte est décalée par rapport au bord gauche de l'écran, et qu'elle a des coins arrondis et une ombre (qui exprime l'élévation de la carte). La zone entière est appelée "conteneur". Hormis le conteneur lui-même, tous les éléments qu'il contient sont facultatifs.

Vous pouvez ajouter les éléments suivants à un conteneur : du texte d'en-tête, une vignette ou un avatar, un texte de sous-titre, des séparateurs, et même des boutons et des icônes. La fiche que nous venons de créer, par exemple, contient deux valeurs TextView (une pour le titre et une pour le texte secondaire) dans une LinearLayout, alignées en bas de la fiche.

Les fiches s'affichent généralement dans une collection avec d'autres fiches. Dans la section suivante de cet atelier de programmation, nous les présenterons sous forme de collection dans une grille.

5. Créer une grille de cartes

Lorsque plusieurs fiches sont présentes sur un écran, elles sont regroupées dans une ou plusieurs collections. Les cartes d'une grille sont coplanaires : elles ont toute la même élévation au repos (c'est-à-dire lorsqu'elles ne sont pas sélectionnées ou déplacées, ce que nous ne ferons pas ici).

Configurer la grille de cartes

Consultez le fichier shr_product_card.xml que nous vous avons fourni :

shr_product_card.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:cardBackgroundColor="@android:color/white"
   app:cardElevation="2dp"
   app:cardPreventCornerOverlap="true">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       <com.android.volley.toolbox.NetworkImageView
           android:id="@+id/product_image"
           android:layout_width="match_parent"
           android:layout_height="@dimen/shr_product_card_image_height"
           android:background="?attr/colorPrimaryDark"
           android:scaleType="centerCrop" />

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:padding="16dp">

           <TextView
               android:id="@+id/product_title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_title"
               android:textAppearance="?attr/textAppearanceHeadline6" />

           <TextView
               android:id="@+id/product_price"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_description"
               android:textAppearance="?attr/textAppearanceBody2" />
       </LinearLayout>
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Cette mise en page de cartes contient une fiche avec une image (ici, un NetworkImageView, qui nous permet d'inclure des images à partir d'une URL) et deux TextViews.

Ensuite, examinez le ProductCardRecyclerViewAdapter que nous vous avons fourni. Il se trouve dans le même package que ProductGridFragment.

ProductCardRecyclerViewAdapter.java

package com.google.codelabs.mdc.java.shrine;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.codelabs.mdc.java.shrine.network.ImageRequester;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

import java.util.List;

/**
* Adapter used to show a simple grid of products.
*/
public class ProductCardRecyclerViewAdapter extends RecyclerView.Adapter<ProductCardViewHolder> {

   private List<ProductEntry> productList;
   private ImageRequester imageRequester;

   ProductCardRecyclerViewAdapter(List<ProductEntry> productList) {
       this.productList = productList;
       imageRequester = ImageRequester.getInstance();
   }

   @NonNull
   @Override
   public ProductCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shr_product_card, parent, false);
       return new ProductCardViewHolder(layoutView);
   }

   @Override
   public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

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

La classe d'adaptateur ci-dessus gère le contenu de notre grille. Pour déterminer ce que chaque vue doit faire avec son contenu donné, nous allons bientôt écrire le code de onBindViewHolder().

Dans le même package, vous pouvez également consulter ProductCardViewHolder. Cette classe stocke les vues qui affectent la mise en page des cartes afin de pouvoir les modifier ultérieurement.

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       // TODO: Find and store views from itemView
   }
}

Pour configurer notre grille, nous devons d'abord supprimer l'espace réservé MaterialCardView de shr_product_grid_fragment.xml. Vous devez ensuite ajouter le composant représentant notre grille de cartes. Dans ce cas, ajoutez un composant RecyclerView à votre shr_product_grid_fragment.xml sous votre composant XML AppBarLayout :

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:paddingStart="@dimen/shr_product_grid_spacing"
   android:paddingEnd="@dimen/shr_product_grid_spacing"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.core.widget.NestedScrollView>

Votre shr_product_grid_fragment.xml doit se présenter comme suit :

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>

   <androidx.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="56dp"
       android:background="@color/productGridBackgroundColor"
       android:paddingStart="@dimen/shr_product_grid_spacing"
       android:paddingEnd="@dimen/shr_product_grid_spacing"
       app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/recycler_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </androidx.core.widget.NestedScrollView>

</FrameLayout>

Enfin, dans onCreateView(), ajoutez le code d'initialisation RecyclerView dans ProductGridFragment.java après avoir appelé setUpToolbar(view) et avant l'instruction return :

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   ...
   setUpToolbar(view);

   // Set up the RecyclerView
   RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
   recyclerView.setHasFixedSize(true);
   recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
   ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(getResources()));
   recyclerView.setAdapter(adapter);
   int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
   int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
   recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

   return view;
}

L'extrait de code ci-dessus contient les étapes d'initialisation nécessaires pour configurer un RecyclerView. Cela inclut la configuration du gestionnaire de mise en page de RecyclerView, ainsi que l'initialisation et la configuration de l'adaptateur de RecyclerView.

Votre fichier ProductGridFragment.java devrait maintenant se présenter comme suit :

ProductGridFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;


import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }

   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       // Set up the RecyclerView
       RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
       recyclerView.setHasFixedSize(true);
       recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
       ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(getResources()));
       recyclerView.setAdapter(adapter);
       int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
       int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
       recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

       return view;
   }

   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

Compilez et exécutez.

f9aeab846fc3bb4c.png

Les fiches sont maintenant disponibles. Comme ils n'affichent rien pour le moment, ajoutons des données produit.

Ajouter des images et du texte

Pour chaque fiche, ajoutez une image, un nom de produit et un prix. Notre abstraction ViewHolder contient les vues de chaque fiche. Dans ViewHolder, ajoutez les trois vues comme suit :

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;

import com.android.volley.toolbox.NetworkImageView;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public NetworkImageView productImage;
   public TextView productTitle;
   public TextView productPrice;

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       productImage = itemView.findViewById(R.id.product_image);
       productTitle = itemView.findViewById(R.id.product_title);
       productPrice = itemView.findViewById(R.id.product_price);
   }
}

Dans l'adaptateur de notre RecyclerView, dans ViewHolder,, mettez à jour la méthode onBindViewHolder() pour définir les informations sur chaque vue :

ProductCardRecyclerViewAdapter.java

@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
   if (productList != null && position < productList.size()) {
       ProductEntry product = productList.get(position);
       holder.productTitle.setText(product.title);
       holder.productPrice.setText(product.price);
       imageRequester.setImageFromUrl(holder.productImage, product.url);
   }
}

Le code ci-dessus indique à l'adaptateur de notre RecyclerView ce qu'il doit faire avec chaque fiche, à l'aide d'un ViewHolder.

Ici, elle définit les données textuelles sur chacun des TextView de ViewHolder et appelle un ImageRequester pour obtenir une image à partir d'une URL. ImageRequester est une classe que nous avons fournie à titre indicatif et qui utilise la bibliothèque Volley. (Il s'agit d'un sujet qui n'est pas abordé dans cet atelier de programmation, mais n'hésitez pas à explorer le code par vous-même.)

Compilez et exécutez:

249db074eff043f4.png

Nos produits apparaissent désormais dans l'application !

6. Récapitulatif

Notre application propose un fonctionnement de base permettant à l'utilisateur de passer de l'écran de connexion à un écran d'accueil où les produits sont affichés. Quelques lignes de code nous ont suffi pour ajouter une barre d'application supérieure avec un titre et trois boutons, ainsi qu'une grille de fiches pour présenter le contenu de notre application. L'écran d'accueil obtenu est simple et fonctionnel, et présente une structure de base et des contenus exploitables.

Étapes suivantes

Avec la barre d'application supérieure, la fiche, le champ de texte et le bouton, nous avons utilisé quatre composants Material Design de base de la bibliothèque MDC-Android. Pour découvrir encore plus de composants, consultez le catalogue des composants MDC-Android.

Bien qu'elle soit entièrement fonctionnelle, notre application ne reflète pas encore de marque particulière. Dans l'atelier MDC-103 : Utilisation des thèmes de Material Design (couleur, formes, élévation et type), nous allons personnaliser le style de ces composants pour exprimer une marque moderne et dynamique.

La réalisation de cet atelier de programmation m'a demandé un temps et des efforts raisonnables

Tout à fait d'accord D'accord Ni d'accord, ni pas d'accord Pas d'accord Pas du tout d'accord

Je souhaite continuer à utiliser Material Components

Tout à fait d'accord D'accord Ni d'accord, ni pas d'accord Pas d'accord Pas du tout d'accord