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

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 travaillant pour 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 éléments Material Components (MDC) pour créer une page de connexion : des champs de texte et des boutons comportant des animations "tâche d'encre". 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

Composants MDC-Android 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)

Quel est votre niveau d'expérience en termes de création d'applications Android ?

Débutant Intermédiaire Expert

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

Si vous avez fini l'atelier de programmation MDC-101, votre code devrait être prêt pour commencer cet atelier. Passez à 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

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

L'application de départ se trouve dans le répertoire material-components-android-codelabs-102-starter/kotlin. Assurez-vous d'utiliser la commande cd pour accéder à ce répertoire 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 kotlin > shrine(ou recherchez shrine sur votre ordinateur) pour ouvrir le projet Shipping.
  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.

Ajouter des dépendances de projet

Le projet nécessite une dépendance à la bibliothèque de support MDC-Android. L'exemple de code que vous avez téléchargé devrait déjà inclure cette dépendance, mais il est recommandé de suivre les étapes suivantes pour en être sûr.

  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 indiquée à gauche du bouton d'exécution / de lecture 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 de vos appareils Android figurent déjà dans la liste de ceux 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.

Maintenant que l'écran de connexion est en place, ajoutons quelques produits dans l'application.

L'écran d'accueil s'affiche lorsque la page de connexion est fermée, avec un écran indiquant "You did it!" (Vous avez réussi !). Parfait ! À présent, notre utilisateur ne peut effectuer aucune action et n'a aucun moyen de savoir où il se trouve dans l'application. Pour résoudre ce problème, il est temps d'ajouter la navigation.

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

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 le bloc <LinearLayout> contenant le message "Bravo !". TextView et remplacez-le par ce qui suit :

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 maintenant 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 dans la nôtre.

Ajouter une icône de navigation

Toujours dans shr_product_grid_fragment.xml, ajoutez les éléments suivants 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 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: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 à la fin de la barre d'application. Dans Android, ces boutons sont appelés boutons d'action. Nous allons styliser la barre d'application supérieure et ajouter des boutons d'action à son menu de manière programmatique.

Dans la fonction onCreateView de ProductGridFragment.kt, définissez le Toolbar de activity à utiliser comme ActionBar à l'aide de setSupportActionBar. Vous pouvez le faire après la création de la vue avec inflater.

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   return view;
}

Ensuite, juste en dessous de la méthode que nous venons de modifier pour configurer la barre d'outils, remplaçons onCreateOptionsMenu pour insérer le contenu de shr_toolbar_menu.xml dans la barre d'outils :

ProductGridFragment.kt

override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
   super.onCreateOptionsMenu(menu, menuInflater)
}

Enfin, remplacez onCreate() dans ProductGridFragment.kt, puis après avoir appelé super(), appelez setHasOptionMenu avec true :

ProductGridFragment.kt

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setHasOptionsMenu(true)
}

Les extraits de code ci-dessus définissent la barre d'application de notre mise en page XML comme barre d'action pour cette activité. Le rappel onCreateOptionsMenu indique à l'activité ce qu'il faut utiliser comme menu. Dans ce cas, il placera les éléments de menu de R.menu.shr_toolbar_menu 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 apportées, votre fichier ProductGridFragment.kt devrait se présenter comme suit :

ProductGridFragment.kt

package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the tool bar
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       return view;
   }

   override fun 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 :

La barre d'outils comporte désormais une icône de navigation, un titre et deux icônes d'action sur la droite. 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.

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. Ajoutez le code suivant dans shr_product_grid_fragment.xml 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>

Compiler et exécuter :

Dans cet aperçu, vous pouvez voir que la fiche est positionnée avec une marge à gauche, ses coins sont arrondis et elle projette une ombre (représentant son élévation). L'élément entier est appelé "conteneur". Hormis le conteneur, tous les éléments qu'il contient sont facultatifs.

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

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

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 dans cet atelier de programmation).

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 carte contient une carte avec une image (dans ce cas, un NetworkImageView, qui nous permet de charger et d'afficher des images à partir d'une URL) et deux TextViews.

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

ProductCardRecyclerViewAdapter.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry

/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
       val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
       return ProductCardViewHolder(layoutView)
   }

   override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   override fun getItemCount(): Int {
       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 le contenu qui lui est attribué, nous allons bientôt écrire le code pour onBindViewHolder().

Vous pouvez également consulter ProductCardViewHolder dans le même package. Cette classe stocke les vues qui affectent la mise en page de notre carte, afin que nous puissions les modifier ultérieurement.

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import androidx.recyclerview.widget.RecyclerView

class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
   : RecyclerView.ViewHolder(itemView)

Pour configurer notre grille, nous allons d'abord supprimer le MaterialCardView de l'espace réservé de shr_product_grid_fragment.xml. Vous devez ensuite ajouter le composant représentant notre grille de cartes. Dans ce cas, nous utiliserons un RecyclerView. Ajoutez le 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 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: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.kt après avoir appelé setUpToolbar(view) et avant l'instruction return :

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   // Set up the RecyclerView
   view.recycler_view.setHasFixedSize(true)
   view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
   val adapter = ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(resources))
   view.recycler_view.adapter = adapter
   val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
   val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
   view.recycler_view.addItemDecoration(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 définition du gestionnaire de mise en page de RecyclerView, ainsi que l'initialisation et la définition de l'adaptateur de RecyclerView.

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

ProductGridFragment.kt

package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the toolbar.
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       // Set up the RecyclerView
       view.recycler_view.setHasFixedSize(true)
       view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
       val adapter = ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(resources))
       view.recycler_view.adapter = adapter
       val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
       val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
       view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))

       return view;
   }

   override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
       super.onCreateOptionsMenu(menu, menuInflater)
   }
}

Compiler et exécuter :

Les fiches sont désormais disponibles ! Ils ne montrent encore rien, alors ajoutons des données produit.

Ajouter des images et du texte

Pour chaque fiche, ajoutez une image, le nom du produit et son prix. Notre abstraction ViewHolder contient les vues de chaque carte. Dans notre ViewHolder, ajoutez les trois vues comme suit.

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

import com.android.volley.toolbox.NetworkImageView

class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

   var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
   var productTitle: TextView = itemView.findViewById(R.id.product_title)
   var productPrice: TextView = itemView.findViewById(R.id.product_price)
}

Mettez à jour la méthode onBindViewHolder() dans ProductCardRecyclerViewAdapter pour définir le titre, le prix et l'image de chaque vue de produit, comme indiqué ci-dessous :

ProductCardRecyclerViewAdapter.kt

override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
   if (position < productList.size) {
       val product = productList[position]
       holder.productTitle.text = product.title
       holder.productPrice.text = 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 carte, à l'aide d'un ViewHolder.

Ici, il définit les données de texte 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 pour votre commodité. Elle utilise la bibliothèque Volley (ce sujet ne fait pas partie de cet atelier de programmation, mais n'hésitez pas à explorer le code par vous-même).

Compiler et exécuter :

Nos produits s'affichent désormais dans l'application.

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 essentiels de Material Design de la bibliothèque MDC-Android. Pour découvrir encore plus de composants, consultez le catalogue MDC-Android.

Même si notre application fonctionne parfaitement, elle ne reflète pas encore une identité de marque ni un style particulier. 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