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.
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
etwhen
). - 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
- 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 :
- Ouvrez
activity_main.xml
(app > res > layouts > activity_main.xml) pour afficher l'éditeur de mise en page.
Supprimer l'élément TextView
- Dans l'éditeur de mise en page, sélectionnez la
TextView
dans Component Tree (Arborescence des composants).
- Effectuez un clic droit et sélectionnez Supprimer, ou appuyez sur la touche
Delete
. - Ignorez l'avertissement concernant le
Button
pour le moment. Vous corrigerez ce problème à l'étape suivante.
Ajouter une ImageView à la mise en page
- À partir de la Palette, faites glisser une
ImageView
dans la vue Design (Conception). Placez l'image au-dessus duButton
.
- 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.
- Cliquez sur OK. La vue Design de votre application devrait se présenter comme suit :
- Vous remarquerez deux erreurs dans l'arborescence des composants. Votre
Button
n'est soumis à aucune contrainte verticale, et votreImageView
n'est soumise à aucune contrainte verticale ou horizontale.
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
.
- Ajoutez des contraintes horizontales à
ImageView
. Reliez le côté gauche de votreImageView
au bord gauche de laConstraintLayout
parente. - Reliez le côté droit de votre
ImageView
au bord droit de son parent. Ces contraintes centrent horizontalement l'élémentImageView
dans son parent.
- Ajoutez une contrainte verticale à votre
ImageView
, en connectant le haut l'élémentImageView
au haut du parent. Cette contrainte pousse l'élémentImageView
vers le haut de laConstraintLayout
.
- Ajoutez une contrainte verticale au
Button
, en connectant le haut duButton
au bas de votreImageView
. Cette contrainte colle leButton
sous l'élémentImageView
.
- Sélectionnez à nouveau votre
ImageView
et ajoutez-lui une contrainte verticale. Reliez le bas de l'élémentImageView
au bas du parent. VotreImageView
est désormais centrée verticalement dans laConstraintLayout
.
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 :
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
- 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.
- Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
- 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é.
Ajouter les images de dés à votre application
- 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).
- Click the + below Resource Manager, and select Import Drawables. Un explorateur de fichiers s'ouvre.
- 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. - Cliquez sur Open (Ouvrir).
- Cliquez sur Next (Suivant), puis sur Import (Importer) pour confirmer que vous souhaitez importer ces six ressources.
- 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.
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
- Dans l'éditeur de conception, sélectionnez l'élément
ImageView
. - 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.
- 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
.
- Sélectionnez le drawable
dice_1
, puis cliquez sur OK.
Et voilà ! Le ImageView
occupe la totalité de l'écran.
Ensuite, vous allez ajuster la largeur et la hauteur de votre ImageView
pour qu'elle ne cache pas le Button
.
- 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. - À 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.
Vous constaterez peut-être que le Button
est un peu trop proche de l'image.
- Utilisez le widget Constraint pour ajouter une marge supérieure de 16 dp au bouton.
Une fois la vue Design actualisée, votre application a une bien meilleure apparence.
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 :
En effet, votre code fait toujours référence à la TextView
que vous avez supprimée de la mise en page.
- 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.
- 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()
- Toujours dans
rollDice()
, créez une variable de typeImageView
appeléediceImage
. Définissez sa valeur sur l'élémentImageView
de la mise en page. Utilisez la méthodefindViewById()
et transmettez l'ID de ressourceR.id.imageView
de votreImageView
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).
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.
- 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'imagedice_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)
}
- 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).
Lorsque vous appuyez sur le bouton, une image de dé représentant la valeur 2 apparaît. Parfait !
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()
- Dans la méthode
rollDice()
, supprimez la ligne de code qui définit systématiquement l'ID de ressource de l'image surdice_2
.
diceImage.setImageResource(R.drawable.dice_2)
- Remplacez-la par une instruction
when
qui met à jour votreImageView
en fonction de la valeur dudiceRoll
.
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)
}
}
- Exécutez l'application. Appuyez sur le bouton Roll pour remplacer l'image du dé par une valeur autre que 2. Ça fonctionne !
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.
- 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.
- 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)
- 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()
}
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
- Cliquez sur l'URL indiquée. La page GitHub du projet s'ouvre dans un navigateur.
- Sur la page GitHub du projet, cliquez sur le bouton Code pour afficher une boîte de dialogue.
- 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.
- Recherchez le fichier sur votre ordinateur (il se trouve probablement dans le dossier Téléchargements).
- 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
- Lancez Android Studio.
- 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).
Remarque : Si Android Studio est déjà ouvert, sélectionnez l'option de menu File > New > Import Project (Fichier > Nouveau > Importer un projet).
- 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.
- Double-cliquez sur le dossier de ce projet.
- Attendez qu'Android Studio ouvre le projet.
- Cliquez sur le bouton Run (Exécuter) pour créer et exécuter l'application. Assurez-vous qu'elle fonctionne correctement.
- 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 uneImageView
. - Vous avez utilisé des instructions de structure de contrôle, comme les expressions
if / else
ouwhen
, 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 :
- 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 fichierMainActivity.kt
?
Vérifiez votre travail :
Une fois terminée, votre application devrait fonctionner sans erreur et afficher les deux dés.