Ajouter des images à l'application Dice Roller

1. Avant de commencer

Dans cet atelier de programmation, vous allez ajouter des images de dés à votre application Android Dice Roller. Assurez-vous d'abord d'avoir terminé l'atelier de programmation précédent, qui pose les bases de l'application Dice Roller.

Au lieu d'afficher la valeur du lancer de dé dans une TextView, votre application affiche l'image d'un dé correspondant au résultat obtenu, ce qui rendra l'expérience utilisateur beaucoup plus visuelle et immersive.

c7f0d42525da7431.png

Vous devrez ajouter ces images en tant que ressources de votre application. Un lien de téléchargement vous sera fourni. Vous utiliserez une instruction when en Kotlin pour écrire le code déterminant l'image de dé à afficher.

Conditions préalables

  • Vous avez terminé l'atelier de programmation "Créer une application interactive : Dice Roller".
  • Vous savez écrire des instructions de structure de contrôle (instructions if / else et when).
  • Vous savez mettre à jour l'interface utilisateur de l'application en fonction d'une entrée utilisateur (modification du fichier MainActivity.kt).
  • Vous savez ajouter un écouteur de clics à un Button..
  • Vous savez ajouter des ressources image à une application Android.

Points abordés

  • Comment mettre à jour une ImageView pendant l'exécution de l'application
  • Comment personnaliser le comportement de votre application en fonction de différentes conditions (à l'aide d'une instruction when)

Objectifs de l'atelier

  • Créer une application Dice Roller pour Android dotée d'un Button pour lancer un dé et mettre à jour l'image à l'écran

Ce dont vous avez besoin

  • Un ordinateur sur lequel est installé Android Studio
  • Une connexion Internet permettant de télécharger les images de dés

2. Modifier la mise en page de l'application

Dans cette tâche, vous allez remplacer la TextView de votre mise en page par une ImageView qui affiche une image correspondant au résultat du lancer de dé.

Ouvrir l'application Dice Roller

  1. Ouvrez et exécutez l'application Dice Roller de l'atelier de programmation précédent dans Android Studio. Vous pouvez utiliser votre propre code ou celui de la solution.

L'application devrait se présenter comme suit :

2e8416293e597725.png

  1. Ouvrez activity_main.xml (app > res > layouts > activity_main.xml) pour afficher l'éditeur de mise en page.

Supprimer l'élément TextView

  1. Dans l'éditeur de mise en page, sélectionnez la TextView dans Component Tree (Arborescence des composants).

a6fc189dac34ee71.png

  1. Effectuez un clic droit et sélectionnez Supprimer, ou appuyez sur la touche Delete.
  2. Ignorez l'avertissement concernant le Button pour le moment. Vous corrigerez ce problème à l'étape suivante.

Ajouter une ImageView à la mise en page

  1. À partir de la Palette, faites glisser une ImageView dans la vue Design (Conception). Placez l'image au-dessus du Button.

91f6e2be0a01fbf.png

  1. Dans la boîte de dialogue Pick a Resource (Choisir une ressource), sélectionnez avatars (avatars) sous Sample data (Échantillons de données). Il s'agit de l'image temporaire que vous utiliserez en attendant d'ajouter les dés lors de la tâche suivante.

824493e9927da401.png

  1. Cliquez sur OK. La vue Design de votre application devrait se présenter comme suit :

f9d5ee87018baee.png

  1. Vous remarquerez deux erreurs dans l'arborescence des composants. Votre Button n'est soumis à aucune contrainte verticale, et votre ImageView n'est soumise à aucune contrainte verticale ou horizontale.

b8c3b83124c31ff.png

Le Button a perdu sa contrainte verticale lorsque vous avez supprimé la TextView sous laquelle il était positionné. Vous devez maintenant positionner votre ImageView et le Button en dessous.

Positionner le bouton et l'ImageView

Vous devez centrer verticalement votre ImageView dans l'écran, indépendamment de l'emplacement du Button.

  1. Ajoutez des contraintes horizontales à ImageView. Reliez le côté gauche de votre ImageView au bord gauche de la ConstraintLayout parente.
  2. Reliez le côté droit de votre ImageView au bord droit de son parent. Ces contraintes centrent horizontalement l'élément ImageView dans son parent.

9848bb6319e11777.png

  1. Ajoutez une contrainte verticale à votre ImageView, en connectant le haut l'élément ImageView au haut du parent. Cette contrainte pousse l'élément ImageView vers le haut de la ConstraintLayout.

2d8d134e6292d48f.png

  1. Ajoutez une contrainte verticale au Button, en connectant le haut du Button au bas de votre ImageView. Cette contrainte colle le Button sous l'élément ImageView.

b6d3dcee6c7a51fc.png

  1. Sélectionnez à nouveau votre ImageView et ajoutez-lui une contrainte verticale. Reliez le bas de l'élément ImageView au bas du parent. Votre ImageView est désormais centrée verticalement dans la ConstraintLayout.

Tous les avertissements concernant les contraintes devraient avoir disparu.

Suite à ces opérations, la vue Design devrait ressembler à ceci, avec l'élément ImageView au centre et le Button juste en dessous :

1b05a6d2fd56459f.png

Vous remarquerez peut-être un avertissement concernant l'élément ImageView dans l'arborescence des composants, indiquant que vous devez ajouter une description du contenu à votre ImageView. Ne vous préoccupez pas de cet avertissement pour le moment. Dans la suite de l'atelier, vous définirez la description du contenu de ImageView en fonction de l'image affichée. Cette modification sera effectuée dans le code Kotlin.

3. Ajouter les images de dés

Dans cette tâche, vous allez télécharger des images de dés et les ajouter à votre application.

Télécharger les images de dés

  1. Utilisez ce lien pour télécharger sur votre ordinateur le fichier ZIP contenant les images de dés. Attendez la fin du téléchargement.
  2. Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
  3. Double-cliquez sur le fichier ZIP pour le décompresser. Cette opération crée un dossier dice_images contenant six fichiers image, qui affichent les valeurs de 1 à 6 sur un dé.

43c95351759ada02.png

Ajouter les images de dés à votre application

  1. Dans Android Studio, cliquez sur View > Tool Windows > Resource Manager (Vue > Fenêtres d'outil > Gestionnaire de ressources) dans les menus ou cliquez sur l'onglet Resource Manager (Gestionnaire de ressources) à gauche de la fenêtre Project (Projet).
  2. Click the + below Resource Manager, and select Import Drawables. Un explorateur de fichiers s'ouvre.

67186ea5d631bc8a.png

  1. Recherchez et sélectionnez les six fichiers image représentant les dés. Vous pouvez sélectionner le premier fichier et maintenir la touche Shift enfoncée pour sélectionner les autres.
  2. Cliquez sur Open (Ouvrir).
  3. Cliquez sur Next (Suivant), puis sur Import (Importer) pour confirmer que vous souhaitez importer ces six ressources.

a45dff94a19e2722.png

a7ad66d623ac73c2.png

  1. Si les fichiers ont bien été importés, les six images devraient s'afficher dans le gestionnaire de ressources (app > res > drawable) de votre application.

ab68f82b385fc83e.png

Bravo ! Dans la tâche suivante, vous exploiterez ces images dans votre application.

Important : Vous pourrez utiliser les ID de ressource suivants pour faire référence aux images dans votre code Kotlin.

  • R.drawable.dice_1
  • R.drawable.dice_2
  • R.drawable.dice_3
  • R.drawable.dice_4
  • R.drawable.dice_5
  • R.drawable.dice_6

4. Exploiter les images de dés

Remplacer l'image d'avatar

  1. Dans l'éditeur de conception, sélectionnez l'élément ImageView.
  2. Accédez à la rubrique Attributes (Attributs). Dans la section Declared Attributes (Attributs déclarés), recherchez l'attribut d'outil srcCompat. Il est défini sur l'image d'avatar.

N'oubliez pas que l'attribut d'outil srcCompat utilise l'image fournie uniquement dans la vue Design d'Android Studio. Cette image n'est visible que par les développeurs, pendant la création de l'application, et ne sera pas visible lorsque l'application est exécutée sur un émulateur ou un appareil.

  1. Cliquez sur l'aperçu miniature de l'avatar. Une boîte de dialogue s'ouvre pour vous permettre de choisir une nouvelle ressource à utiliser pour cette ImageView.

d8a26941179b3bdf.png

  1. Sélectionnez le drawable dice_1, puis cliquez sur OK.

Et voilà ! Le ImageView occupe la totalité de l'écran.

1072e9fdd637afd9.png

Ensuite, vous allez ajuster la largeur et la hauteur de votre ImageView pour qu'elle ne cache pas le Button.

  1. Dans la fenêtre Attributes, sous le widget Constraints (Contraintes), recherchez les attributs layout_width et layout_height. Comme ils sont actuellement configurés sur wrap_content, votre ImageView sera aussi haute et large que l'image source qu'elle contient.
  2. À la place, définissez une largeur fixe de 160 dp et une hauteur fixe de 200 dp pour cette ImageView. Appuyez sur Entrée.

Votre ImageView est désormais beaucoup plus petite.

9579582d8775e688.png

Vous constaterez peut-être que le Button est un peu trop proche de l'image.

  1. Utilisez le widget Constraint pour ajouter une marge supérieure de 16 dp au bouton.

8c647d6ae28ef3a6.png

Une fois la vue Design actualisée, votre application a une bien meilleure apparence.

b53f7379bfba8c27.png

Changer l'image du dé lorsque l'utilisateur appuie sur le bouton

La mise en page a été corrigée, mais la classe MainActivity doit être modifiée pour exploiter les images de dés.

L'application comporte actuellement une erreur dans le fichier MainActivity.kt. Si vous essayez d'exécuter l'application, un message signale l'erreur de compilation suivante :

aaecce207cb5fc7.png

En effet, votre code fait toujours référence à la TextView que vous avez supprimée de la mise en page.

  1. Ouvrez le fichier MainActivity.kt (app > java > com.example.diceroller > MainActivity.kt).

Le code fait référence à R.id.textView, mais Android Studio ne reconnaît pas cet élément.

3a923aa53fc3ba8a.png

  1. Dans la méthode rollDice(), sélectionnez tout le code faisant référence à TextView, puis supprimez-le.
// Update the TextView with the dice roll
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = dice.roll().toString()
  1. Toujours dans rollDice(), créez une variable de type ImageView appelée diceImage. Définissez sa valeur sur l'élément ImageView de la mise en page. Utilisez la méthode findViewById() et transmettez l'ID de ressource R.id.imageView de votre ImageView en tant qu'argument d'entrée.
val diceImage: ImageView = findViewById(R.id.imageView)

Si vous ne savez pas comment déterminer l'ID de ressource spécifique de votre ImageView, consultez le champ id en haut de la fenêtre Attributes (Attributs).

cbfc9d5e01a04e32.png

Lorsque vous faites référence à cet ID de ressource dans du code en Kotlin, assurez-vous de saisir sa graphie exacte (i minuscule, V majuscule, sans espaces). Sinon, Android Studio affichera une erreur.

  1. Ajoutez cette ligne de code pour vérifier que vous pouvez bien mettre à jour votre ImageView lorsque l'utilisateur appuie sur le bouton. Le résultat du lancer de dé ne sera pas toujours "2". Nous utiliserons simplement l'image dice_2 à des fins de test.
diceImage.setImageResource(R.drawable.dice_2)

Ce code appelle la méthode setImageResource() sur l'élément ImageView en transmettant l'ID de ressource de l'image dice_2. Cette opération met à jour l'élément ImageView à l'écran afin d'afficher l'image dice_2.

Votre méthode rollDice() devrait maintenant se présenter comme suit :

private fun rollDice() {
    val dice = Dice(6)
    val diceRoll = dice.roll()
    val diceImage: ImageView = findViewById(R.id.imageView)
    diceImage.setImageResource(R.drawable.dice_2)
}
  1. Exécutez votre application pour vérifier qu'elle fonctionne correctement. L'application doit démarrer sur un écran vide, à l'exception du bouton Roll (Lancer).

c29b50554a31d30f.png

Lorsque vous appuyez sur le bouton, une image de dé représentant la valeur 2 apparaît. Parfait !

7df72d671b22853f.png

Vous avez pu modifier l'image suite à une pression sur le bouton. Vous y êtes presque !

5. Afficher la bonne image en fonction du lancer de dé

C'est évident, le résultat du lancer de dé ne sera pas toujours un 2. Utilisez la logique de structure de contrôle que vous avez apprise dans l'atelier de programmation Ajouter un comportement conditionnel pour différents lancers de dés pour faire en sorte que l'image du dé approprié s'affiche à l'écran en fonction du résultat aléatoire du lancer.

Avant de commencer à écrire du code, réfléchissez au comportement de l'application d'un point de vue conceptuel. Rédigez un pseudo-code décrivant ce qui doit se passer. Exemple :

Si l'utilisateur obtient un 1, afficher l'image dice_1.

Si l'utilisateur obtient un 2, afficher l'image dice_2.

Et ainsi de suite.

Le pseudo-code ci-dessus peut être écrit avec des instructions if / else en Kotlin basées sur la valeur du dé.

if (diceRoll == 1) {
   diceImage.setImageResource(R.drawable.dice_1)
} else if (diceRoll == 2) {
   diceImage.setImageResource(R.drawable.dice_2)
}
 ...

Toutefois, écrire une instruction if / else pour chaque cas est assez répétitif. La même logique peut être exprimée plus simplement à l'aide d'une instruction when. Cette approche est plus concise (moins de code). Utilisez-la dans votre application.

when (diceRoll) {
   1 -> diceImage.setImageResource(R.drawable.dice_1)
   2 -> diceImage.setImageResource(R.drawable.dice_2)
   ...

Mettre à jour la méthode rollDice()

  1. Dans la méthode rollDice(), supprimez la ligne de code qui définit systématiquement l'ID de ressource de l'image sur dice_2.
diceImage.setImageResource(R.drawable.dice_2)
  1. Remplacez-la par une instruction when qui met à jour votre ImageView en fonction de la valeur du diceRoll.
   when (diceRoll) {
       1 -> diceImage.setImageResource(R.drawable.dice_1)
       2 -> diceImage.setImageResource(R.drawable.dice_2)
       3 -> diceImage.setImageResource(R.drawable.dice_3)
       4 -> diceImage.setImageResource(R.drawable.dice_4)
       5 -> diceImage.setImageResource(R.drawable.dice_5)
       6 -> diceImage.setImageResource(R.drawable.dice_6)
   }

Une fois les modifications effectuées, la méthode rollDice() devrait se présenter comme suit :

private fun rollDice() {
   val dice = Dice(6)
   val diceRoll = dice.roll()

   val diceImage: ImageView = findViewById(R.id.imageView)

   when (diceRoll) {
       1 -> diceImage.setImageResource(R.drawable.dice_1)
       2 -> diceImage.setImageResource(R.drawable.dice_2)
       3 -> diceImage.setImageResource(R.drawable.dice_3)
       4 -> diceImage.setImageResource(R.drawable.dice_4)
       5 -> diceImage.setImageResource(R.drawable.dice_5)
       6 -> diceImage.setImageResource(R.drawable.dice_6)
   }
}
  1. Exécutez l'application. Appuyez sur le bouton Roll pour remplacer l'image du dé par une valeur autre que 2. Ça fonctionne !

ec209952f84b81bd.png 32fc8979b1984e00.png

Optimiser votre code

Si vous souhaitez rendre votre code encore plus concis, vous pouvez y apporter les modifications suivantes. Elles n'ont pas d'impact visible pour l'utilisateur de votre application, mais rendent votre code plus court et moins répétitif.

Vous avez peut-être remarqué que l'appel à diceImage.setImageResource() apparaît six fois dans votre instruction "when".

when (diceRoll) {
    1 -> diceImage.setImageResource(R.drawable.dice_1)
    2 -> diceImage.setImageResource(R.drawable.dice_2)
    3 -> diceImage.setImageResource(R.drawable.dice_3)
    4 -> diceImage.setImageResource(R.drawable.dice_4)
    5 -> diceImage.setImageResource(R.drawable.dice_5)
    6 -> diceImage.setImageResource(R.drawable.dice_6)
}

La seule différence entre chaque cas est l'ID de ressource utilisé. Cela signifie que vous pouvez créer une variable pour stocker l'ID de la ressource à utiliser. Ensuite, vous ne pouvez appeler diceImage.setImageResource() une seule fois dans votre code, et transmettre l'ID de la ressource appropriée.

  1. Remplacez le code ci-dessus par celui ci-dessous.
val drawableResource = when (diceRoll) {
   1 -> R.drawable.dice_1
   2 -> R.drawable.dice_2
   3 -> R.drawable.dice_3
   4 -> R.drawable.dice_4
   5 -> R.drawable.dice_5
   6 -> R.drawable.dice_6
}

diceImage.setImageResource(drawableResource)

Le nouveau concept introduit ici est qu'une expression when peut renvoyer une valeur. Avec ce nouvel extrait de code, l'expression when renvoie l'ID de ressource correct, qui sera stocké dans la variable drawableResource. Vous pouvez ensuite utiliser cette variable pour mettre à jour la ressource image affichée.

  1. Notez que when est maintenant souligné en rouge. Si vous pointez dessus, le message d'erreur suivant s'affiche : ‘when' expression must be exhaustive, add necessary ‘else' branch (L'expression "when" doit être exhaustive, ajoutez la branche "else" requise).

Cette erreur est due au fait que la valeur de l'expression when est attribuée à la drawableResource. Par conséquent, when doit être exhaustif et traiter tous les cas possibles, afin de toujours renvoyer une valeur, même si vous remplacez le dé par un modèle à 12 faces. Android Studio suggère d'ajouter une branche else. Pour résoudre ce problème, remplacez la case du 6 par else. Les cas 1 à 5 restent inchangés, mais tous les autres, y compris 6, sont gérés par else.

val drawableResource = when (diceRoll) {
   1 -> R.drawable.dice_1
   2 -> R.drawable.dice_2
   3 -> R.drawable.dice_3
   4 -> R.drawable.dice_4
   5 -> R.drawable.dice_5
   else -> R.drawable.dice_6
}

diceImage.setImageResource(drawableResource)
  1. Exécutez l'application pour vous assurer qu'elle fonctionne toujours correctement. Faites un test pour vous assurer que les résultats de 1 à 6 affichent tous l'image de dé correspondante.

Définir une description de contenu appropriée pour votre ImageView

Comme vous avez remplacé les chiffres par des images, les lecteurs d'écran ne peuvent plus interpréter le résultat obtenu. Pour résoudre ce problème, après avoir mis à jour la ressource image, mettez à jour la description du contenu de votre ImageView. La description du contenu doit être une description textuelle du contenu affiché dans l'élément ImageView, afin que les lecteurs d'écran puissent le décrire.

diceImage.contentDescription = diceRoll.toString()

Les lecteurs d'écran peuvent lire à haute voix cette description du contenu. Par conséquent, si l'image du dé correspondant au résultat "6" s'affiche à l'écran, sa description lue à voix haute devrait être "6".

6. Adopter les bonnes pratiques de codage

Créer une expérience de lancement plus intuitive

Lorsque l'utilisateur ouvre l'application pour la première fois, l'écran reste vide (à l'exception du bouton Roll). Cela peut sembler étrange. Les utilisateurs ne savent peut-être pas à quoi s'attendre. Vous pouvez donc modifier l'UI pour afficher un lancer aléatoire de dés lorsque vous démarrez l'application et créez l'Activity. Cela permettra aux utilisateurs de comprendre plus facilement qu'appuyer sur le bouton Roll permet de "lancer le dé".

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val rollButton: Button = findViewById(R.id.button)
    rollButton.setOnClickListener { rollDice() }

    // Do a dice roll when the app starts
    rollDice()
}

ec209952f84b81bd.png

Commenter votre code

Ajoutez des commentaires à votre code pour décrire son contenu.

Une fois toutes ces modifications effectuées, la méthode rollDice() pourrait se présenter comme suit.

/**
* Roll the dice and update the screen with the result.
*/
private fun rollDice() {
    // Create new Dice object with 6 sides and roll the dice
    val dice = Dice(6)
    val diceRoll = dice.roll()

    // Find the ImageView in the layout
    val diceImage: ImageView = findViewById(R.id.imageView)

    // Determine which drawable resource ID to use based on the dice roll
    val drawableResource = when (diceRoll) {
        1 -> R.drawable.dice_1
        2 -> R.drawable.dice_2
        3 -> R.drawable.dice_3
        4 -> R.drawable.dice_4
        5 -> R.drawable.dice_5
        else -> R.drawable.dice_6
    }

    // Update the ImageView with the correct drawable resource ID
    diceImage.setImageResource(drawableResource)

    // Update the content description
    diceImage.contentDescription = diceRoll.toString()
}

Pour obtenir le fichier MainActivity.kt complet, consultez le code de solution sur GitHub (le lien est indiqué dans la section suivante).

Bravo ! Vous avez terminé l'application Dice Roller. Vous pourrez l'apporter lors de votre prochaine soirée de jeu entre amis !

7. Code de solution

Le code de solution de cet atelier de programmation figure dans le projet et le module ci-dessous.

Pour obtenir le code de cet atelier de programmation et l'ouvrir dans Android Studio, procédez comme suit :

Obtenir le code

  1. Cliquez sur l'URL indiquée. La page GitHub du projet s'ouvre dans un navigateur.
  2. Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une boîte de dialogue.

5b0a76c50478a73f.png

  1. Dans la boîte de dialogue, cliquez sur le bouton Download ZIP (Télécharger le fichier ZIP) pour enregistrer le projet sur votre ordinateur. Attendez la fin du téléchargement.
  2. Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
  3. Double-cliquez sur le fichier ZIP pour le décompresser. Un dossier contenant les fichiers du projet est alors créé.

Ouvrir le projet dans Android Studio

  1. Lancez Android Studio.
  2. Dans la fenêtre Welcome to Android Studio (Bienvenue dans Android Studio), cliquez sur Open an existing Android Studio project (Ouvrir un projet Android Studio existant).

36cc44fcf0f89a1d.png

Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > New > Import Project (Fichier > Nouveau > Importer un projet).

21f3eec988dcfbe9.png

  1. Dans la boîte de dialogue Import Project (Importer un projet), accédez à l'emplacement du dossier du projet décompressé. Il se trouve probablement dans le dossier Téléchargements.
  2. Double-cliquez sur le dossier de ce projet.
  3. Attendez qu'Android Studio ouvre le projet.
  4. Cliquez sur le bouton Run (Exécuter) 11c34fc5e516fb1c.png pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.
  5. Parcourez les fichiers du projet dans la fenêtre de l'outil Projet pour voir comment l'application est configurée.

8. Résumé

  • Vous avez utilisé setImageResource() pour modifier l'image affichée dans une ImageView.
  • Vous avez utilisé des instructions de structure de contrôle, comme les expressions if / else ou when, pour gérer différents cas de figure dans votre application (par exemple, pour afficher différentes images en fonction de différentes circonstances).

9. En savoir plus

10. Pour s'entraîner

Action à effectuer :

  1. Ajoutez un autre dé à l'application, de sorte que le bouton Roll génère les résultats de deux dés. De combien de ImageViews avez-vous besoin pour votre mise en page ? Quelles sont les conséquences sur le code du fichier MainActivity.kt ?

Vérifiez votre travail :

Une fois terminée, votre application devrait fonctionner sans erreur et afficher les deux dés.