1. Avant de commencer
Dans cet atelier de programmation, vous utiliserez le code de solution de l'atelier de programmation Présentation de l'état dans Compose afin de créer une calculatrice de pourboire interactive. Celle-ci permettra de calculer et d'arrondir automatiquement le montant d'un pourboire lorsque vous saisissez le montant de la note et le pourcentage de pourboire. Cette image représente l'application finale :

Prérequis
- Vous avez suivi l'atelier de programmation Présentation de l'état dans Compose.
- Vous êtes capable d'ajouter des composables TextetTextFieldà une application.
- Vous connaissez la fonction remember(), l'état, le hissage (hoisting) d'état et la différence entre les fonctions composables avec et sans état.
Points abordés
- Ajouter un bouton d'action à un clavier virtuel
- Définition et mode de fonctionnement d'un composable Switch
- Ajouter des icônes précédant les champs de texte
Objectifs de l'atelier
- Création d'une application intitulée Tip Time permettant de calculer le montant d'un pourboire en fonction du montant de la facture saisi par l'utilisateur et du pourcentage de pourboire.
Ce dont vous avez besoin
- La dernière version d'Android Studio.
- Le code de solution de l'atelier de programmation Présentation de l'état dans Compose
2. Télécharger le code de démarrage
Pour commencer, téléchargez le code de démarrage :
Vous pouvez également cloner le dépôt GitHub du code :
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git $ cd basic-android-kotlin-compose-training-tip-calculator $ git checkout state
Vous pouvez parcourir le code dans le dépôt GitHub Tip Time.
3. Présentation de l'application de démarrage
Cet atelier de programmation commence avec l'application Tip Time issue de l'atelier de programmation précédent Présentation de l'état dans Compose. Il fournit l'interface utilisateur nécessaire pour calculer un pourboire avec un pourcentage fixe. La zone de texte Bill amount (Montant de la facture) permet à l'utilisateur de saisir le coût du service. L'application calcule et affiche le montant du pourboire dans un composable Text.
Exécuter l'application Tip Time
- Ouvrez le projet Tip Time dans Android Studio, puis exécutez l'application sur un émulateur ou un appareil.
- Saisissez un montant de facture. L'application calcule et affiche automatiquement le montant du pourboire.

Dans la configuration actuelle, le pourcentage de pourboire est codé en dur et se monte à 15 %. Dans cet atelier de programmation, vous ajouterez à cette fonctionnalité un champ de texte permettant à l'application de calculer un pourcentage de pourboire personnalisé et d'arrondir son montant.
Ajouter les ressources de chaîne nécessaires
- Dans l'onglet Projet, cliquez sur res > values > string.xml.
- Entre les balises <resources>du fichierstrings.xml, ajoutez les ressources de chaîne suivantes :
<string name="how_was_the_service">Tip Percentage</string>
<string name="round_up_tip">Round up tip?</string>
Le fichier strings.xml doit ressembler à cet extrait de code, qui inclut les chaînes de l'atelier de programmation précédent :
strings.xml
<resources>
    <string name="app_name">Tip Time</string>
    <string name="calculate_tip">Calculate Tip</string>
    <string name="bill_amount">Bill Amount</string>
    <string name="how_was_the_service">Tip Percentage</string>
    <string name="round_up_tip">Round up tip?</string>
    <string name="tip_amount">Tip Amount: %s</string>
</resources>
4. Ajouter un champ de texte pour le pourcentage de pourboire
Le pourboire peut être plus ou moins élevé en fonction de la qualité du service fourni et d'autres raisons. C'est pourquoi l'application doit permettre à l'utilisateur de calculer un pourboire personnalisé. Dans cette section, vous ajouterez un champ de texte dans lequel l'utilisateur pourra saisir un pourcentage de pourboire personnalisé, comme illustré dans l'image ci-dessous :

Vous disposez déjà d'un composable de champ de texte Montant de la facture dans votre application, qui est la fonction modulable EditNumberField() sans état. Dans l'atelier de programmation précédent, vous avez hissé l'état amountInput du composable EditNumberField() vers le composable TipTimeLayout(). C'est pour cela que le composable EditNumberField() est devenu sans état.
Pour ajouter un champ de texte, vous pouvez réutiliser le même composable EditNumberField(), mais avec un libellé différent. Pour effectuer cette modification, vous devez transmettre le libellé en tant que paramètre plutôt que de le coder en dur dans la fonction modulable EditNumberField().
Rendez la fonction modulable EditNumberField() réutilisable :
- Dans le fichier MainActivity.ktdans les paramètres de la fonction modulableEditNumberField(), ajoutez une ressource de chaînelabelde typeInt:
@Composable
fun EditNumberField(
    label: Int,
    value: String,
    onValueChanged: (String) -> Unit,
    modifier: Modifier = Modifier
)
- Dans le corps de la fonction, remplacez l'ID de ressource de la chaîne codée en dur par le paramètre label:
@Composable
fun EditNumberField(
    //...
) {
     TextField(
         //...
         label = { Text(stringResource(label)) },
         //...
     )
}
- Pour indiquer que le paramètre labeldoit être une référence de ressource de chaîne, annotez le paramètre de fonction avec la mention@StringRes:
@Composable
fun EditNumberField(
    @StringRes label: Int,
    value: String,
    onValueChanged: (String) -> Unit,
    modifier: Modifier = Modifier
) 
- Exécutez la commande d'importation suivante :
import androidx.annotation.StringRes
- Dans l'appel EditNumberField()de la fonction composableTipTimeLayout(), définissez le paramètrelabelsur la ressource de chaîneR.string.bill_amount:
EditNumberField(
    label = R.string.bill_amount,
    value = amountInput,
    onValueChanged = { amountInput = it },
    modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth()
)
- Aucune modification visuelle ne devrait apparaître dans le volet Preview (Aperçu).

- Dans la fonction composable TipTimeLayout()après l'appel deEditNumberField(), ajoutez un autre champ de texte pour le pourcentage de pourboire personnalisé. Appelez la fonction modulableEditNumberField()avec les paramètres suivants :
EditNumberField(
    label = R.string.how_was_the_service,
    value = "",
    onValueChanged = { },
    modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth()
)
Une zone de texte supplémentaire est ajoutée pour le pourcentage de pourboire personnalisé.
- L'aperçu de l'application affiche désormais un champ de texte Tip Percentage (Pourcentage de pourboire), comme illustré sur cette image :

- En haut de la fonction composable TipTimeLayout(), ajoutez une propriétévarappeléetipInputpour la variable d'état du champ de texte ajouté. UtilisezmutableStateOf("")pour initialiser la variable et délimitez l'appel avec la fonctionremember:
var tipInput by remember { mutableStateOf("") }
- Dans le nouvel appel de fonction EditNumberField(), définissez le paramètrevaluesur la variabletipInput, puis mettez à jour la variabletipInputdans l'expression lambdaonValueChanged:
EditNumberField(
    label = R.string.how_was_the_service,
    value = tipInput,
    onValueChanged = { tipInput = it },
    modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth()
)
- Dans la fonction TipTimeLayout()après la définition de la variabletipInput. Définissez une variablevalnomméetipPercentqui convertit la variabletipInputen un typeDouble. Utilisez un opérateur Elvis et renvoyez0, si la valeur estnull. Cette valeur peut êtrenullsi le champ de texte est vide.
val tipPercent = tipInput.toDoubleOrNull() ?: 0.0
- Dans la fonction TipTimeLayout(), mettez à jour l'appel de fonctioncalculateTip()et transmettez la variabletipPercenten tant que deuxième paramètre :
val tip = calculateTip(amount, tipPercent)
Le code de la fonction TipTimeLayout() devrait maintenant ressembler à cet extrait de code :
@Composable
fun TipTimeLayout() {
    var amountInput by remember { mutableStateOf("") }
    var tipInput by remember { mutableStateOf("") }
    val amount = amountInput.toDoubleOrNull() ?: 0.0
    val tipPercent = tipInput.toDoubleOrNull() ?: 0.0
    val tip = calculateTip(amount, tipPercent)
    Column(
        modifier = Modifier.padding(40.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = stringResource(R.string.calculate_tip),
            modifier = Modifier
                .padding(bottom = 16.dp)
                .align(alignment = Alignment.Start)
        )
        EditNumberField(
            label = R.string.bill_amount,
            value = amountInput,
            onValueChanged = { amountInput = it },
            modifier = Modifier
                .padding(bottom = 32.dp)
                .fillMaxWidth()
        )
        EditNumberField(
            label = R.string.how_was_the_service,
            value = tipInput,
            onValueChanged = { tipInput = it },
            modifier = Modifier
                .padding(bottom = 32.dp)
                .fillMaxWidth()
        )
        Text(
            text = stringResource(R.string.tip_amount, tip),
            style = MaterialTheme.typography.displaySmall
        )
        Spacer(modifier = Modifier.height(150.dp))
    }
}
- Exécutez l'application sur un émulateur ou un appareil, puis saisissez le montant de la facture et le pourcentage de pourboire. L'application calcule-t-elle correctement le montant du pourboire ?

5. Définir un bouton d'action
Dans l'atelier de programmation précédent, vous avez appris à utiliser la classe KeyboardOptions pour définir le type de clavier. Dans cette section, vous allez découvrir comment définir le bouton d'action du clavier avec la même classe, KeyboardOptions. Un bouton d'action est un bouton situé à l'extrémité du clavier. Voici quelques exemples dans ce tableau :
| Propriété | Bouton d'action du clavier | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
Au cours de cette tâche, vous définirez deux boutons d'action différents pour les zones de texte :
- Un bouton d'action Next (Suivant) pour la zone de texte Bill Amount (Montant de la facture), qui indique que l'utilisateur a terminé la saisie et souhaite passer à la zone de texte suivante.
- Un bouton d'action Done (Terminé) pour la zone de texte Tip Percentage (Pourcentage de pourboire), qui indique que l'utilisateur a terminé de saisir une entrée.
Voici, dans les images ci-dessous, des exemples de claviers comportant ces boutons d'action :
| 
 | 
 | 
Ajouter des options de clavier :
- Dans l'appel TextField()de la fonctionEditNumberField(), transmettez au constructeurKeyboardOptionsun argument nomméimeActiondéfini sur une valeurImeAction.Next. Utilisez la fonctionKeyboardOptions.Default.copy()pour vous assurer d'utiliser les autres options par défaut.
import androidx.compose.ui.text.input.ImeAction
@Composable
fun EditNumberField(
    //...
) {
    TextField(
        //...
        keyboardOptions = KeyboardOptions.Default.copy(
            keyboardType = KeyboardType.Number,
            imeAction = ImeAction.Next
        )
    )
}
- Exécutez l'application sur un émulateur ou un appareil. Le clavier affiche maintenant le bouton d'action Next (Suivant), comme illustré sur cette image :

Notez que le même bouton d'action Next (Suivant) s'affiche sur le clavier lorsque le champ de texte Tip Percentage (Pourcentage de pourboire) est sélectionné. Toutefois, vous avez besoin de deux boutons d'action différents pour les champs de texte. Vous allez rapidement résoudre ce problème.
- Examinez la fonction EditNumberField(). Le paramètrekeyboardOptionsde la fonctionTextField()est codé en dur. Pour créer différents boutons d'action pour les champs de texte, vous devez transmettre l'objetKeyboardOptionsen tant qu'argument, ce que vous ferez à l'étape suivante.
// No need to copy, just examine the code.
fun EditNumberField(
    @StringRes label: Int,
    value: String,
    onValueChanged: (String) -> Unit,
    modifier: Modifier = Modifier
) {
    TextField(
        //...
        keyboardOptions = KeyboardOptions.Default.copy(
           keyboardType = KeyboardType.Number,
           imeAction = ImeAction.Next
        )
    )
}
- Dans la définition de la fonction EditNumberField(), ajoutez un paramètrekeyboardOptionsde typeKeyboardOptions. Dans le corps de la fonction, attribuez-le au paramètre nommékeyboardOptionsde la fonctionTextField():
@Composable
fun EditNumberField(
    @StringRes label: Int,
    keyboardOptions: KeyboardOptions,
    // ...
){
    TextField(
        //...
        keyboardOptions = keyboardOptions
    )
}
- Dans la fonction TipTimeLayout(), modifiez le premier appel de fonctionEditNumberField(), puis transmettez le paramètre nommékeyboardOptionspour le champ de texte Bill Amount (Montant de la facture) :
EditNumberField(
    label = R.string.bill_amount,
    keyboardOptions = KeyboardOptions.Default.copy(
        keyboardType = KeyboardType.Number,
        imeAction = ImeAction.Next
    ),
    // ...
)
- Dans le second appel de fonction EditNumberField(), remplacez la valeurimeActiondu champ de texte Tip Percentage (Pourcentage de pourboire) parImeAction.Done. La fonction devrait se présenter comme suit :
EditNumberField(
    label = R.string.how_was_the_service,
    keyboardOptions = KeyboardOptions.Default.copy(
        keyboardType = KeyboardType.Number,
        imeAction = ImeAction.Done
    ),
    // ...
)
- Exécutez l'application. Les boutons Suivant et Terminé s'affichent, comme illustré sur les images suivantes :
| 
 | 
 | 
- Saisissez le montant d'une facture, cliquez sur le bouton d'action Next (Suivant), saisissez un pourcentage de pourboire, puis cliquez sur le bouton d'action Done (Terminé). Le clavier se ferme.

6. Ajouter un bouton bascule
Un bouton bascule permet d'activer ou de désactiver l'état d'un unique élément.

Un bouton bascule à deux états permet à l'utilisateur de choisir entre deux options. Un bouton bascule se compose d'un conteneur, d'un curseur et d'une icône facultative, comme illustré sur les images suivantes :

Le bouton bascule est une commande de sélection qui vous permet d'indiquer un choix ou de déclarer une préférence, telles que des paramètres, comme illustré dans cette image :

L'utilisateur peut soit faire glisser le curseur d'avant en arrière pour définir l'option de son choix, soit simplement appuyer sur le bouton pour l'activer. Vous trouverez un autre exemple d'activation et de désactivation dans l'image GIF ci-dessous, où le paramètre "Display options" (Options visuelles) est défini sur Dark mode (Mode sombre) :

Pour en savoir plus, consultez la documentation sur les boutons bascules.
Vous pouvez utiliser le composable Switch pour que l'utilisateur ait la possibilité d'arrondir le pourboire au nombre entier le plus proche, comme illustré dans cette image :

Ajoutez une ligne pour les composables Text et Switch :
- Après la fonction EditNumberField(), ajoutez une fonction modulableRoundTheTipRow(), puis transmettez un élémentModifierpar défaut comme des arguments semblables à la fonctionEditNumberField():
@Composable
fun RoundTheTipRow(modifier: Modifier = Modifier) {
}
- Implémentez la fonction RoundTheTipRow(), ajoutez un composableRowde mise en page avec l'élémentmodifiersuivant afin de définir la largeur maximale à l'écran pour les éléments enfants. Centrez l'alignement et assurez-vous que la taille correspond à une taille de48dp:
Row(
   modifier = modifier
       .fillMaxWidth()
       .size(48.dp),
   verticalAlignment = Alignment.CenterVertically
) {
}
- Exécutez la commande d'importation suivante :
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
- Dans le bloc lambda du composable de mise en page Row, ajoutez un composableTextqui utilisera la ressource de chaîneR.string.round_up_tippour afficher une chaîneRound up tip?:
Text(text = stringResource(R.string.round_up_tip))
- Après le composable Text, ajoutez un composableSwitch, puis transmettez un paramètre nommécheckedàroundUpet un paramètreonCheckedChangedéfini suronRoundUpChanged.
Switch(
    checked = roundUp,
    onCheckedChange = onRoundUpChanged,
)
Ce tableau contient des informations sur ces paramètres, qui sont les mêmes que ceux que vous avez définis pour la fonction RoundTheTipRow() :
| Paramètre | Description | 
| 
 | Indique si le bouton bascule est activé. Il s'agit de l'état du composable  | 
| 
 | Rappel à appeler en cas de clic sur le bouton bascule. | 
- Exécutez la commande d'importation suivante :
import androidx.compose.material3.Switch
- Dans la fonction RoundTheTipRow(), ajoutez un paramètreroundUpde typeBooleanet une fonction lambdaonRoundUpChangedqui accepte une valeurBooleanet ne renvoie rien :
@Composable
fun RoundTheTipRow(
    roundUp: Boolean,
    onRoundUpChanged: (Boolean) -> Unit,
    modifier: Modifier = Modifier
)
Cette action hisse l'état du bouton bascule.
- Dans le composable Switch, ajoutez cet élémentmodifierpour aligner le composableSwitchavec la fin de l'écran :
       Switch(
           modifier = modifier
               .fillMaxWidth()
               .wrapContentWidth(Alignment.End),
           //...
       )
- Exécutez la commande d'importation suivante :
import androidx.compose.foundation.layout.wrapContentWidth
- Dans la fonction TipTimeLayout(), ajoutez une variable var pour l'état du composableSwitch. Créez une variablevarnomméeroundUpet définissez-la surmutableStateOf(), avecfalsecomme valeur initiale. Délimitez l'appel avecremember { }.
fun TipTimeLayout() {
    //...
    var roundUp by remember { mutableStateOf(false) }
    //...
    Column(
        ...
    ) {
      //...
   }
}
Il s'agit de la variable d'état du composable Switch. "false" est l'état par défaut.
- Dans le bloc Columnde la fonctionTipTimeLayout()après le champ de texte Tip Percentage (Pourcentage de pourboire), appelez la fonctionRoundTheTipRow()avec les arguments suivants : paramètre nomméroundUpdéfini surroundUpet paramètre nomméonRoundUpChangeddéfini sur un rappel lambda qui met à jour la valeurroundUp:
@Composable
fun TipTimeLayout() {
    //...
    Column(
        ...
    ) {
        Text(
            ...
        )
        Spacer(...)
        EditNumberField(
            ...
        )
        EditNumberField(
            ...
        )
        RoundTheTipRow(
             roundUp = roundUp,
             onRoundUpChanged = { roundUp = it },
             modifier = Modifier.padding(bottom = 32.dp)
         )
        Text(
            ...
        )
    }
}
La ligne Round up tip? (Arrondir le montant du pourboire ?) s'affiche.
- Exécutez l'application. Le bouton bascule Round up tip? (Arrondir le montant du pourboire ?) s'affiche.

- Saisissez le montant de la facture et le pourcentage de pourboire, puis cliquez sur le bouton Round up tip? (Arrondir le montant du pourboire ?). Le montant du pourboire n'est pas arrondi, car vous n'avez pas encore mis à jour la fonction calculateTip(), ce que vous ferez dans la section suivante.
Mettre à jour la fonction calculateTip() pour arrondir le pourboire
Modifiez la fonction calculateTip() pour qu'elle accepte une variable Boolean afin d'arrondir le pourboire à l'entier le plus proche :
- Pour arrondir le pourboire, la fonction calculateTip()doit connaître l'état du bouton bascule, qui correspond à une valeurBoolean. Dans la fonctioncalculateTip(), ajoutez un paramètreroundUpde typeBoolean:
private fun calculateTip(
    amount: Double,
    tipPercent: Double = 15.0,
    roundUp: Boolean
): String { 
    //...
}
- Dans la fonction calculateTip(), avant l'instructionreturn, ajoutez une conditionif()qui vérifiera la valeurroundUp. Si la valeur de l'élémentroundUpesttrue, définissez une variabletipet ajoutezkotlin.math.ceil(), puis transmettez la fonctiontipcomme argument :
if (roundUp) {
    tip = kotlin.math.ceil(tip)
}
La fonction calculateTip() terminée devrait ressembler à ceci :
private fun calculateTip(amount: Double, tipPercent: Double = 15.0, roundUp: Boolean): String {
    var tip = tipPercent / 100 * amount
    if (roundUp) {
        tip = kotlin.math.ceil(tip)
    }
    return NumberFormat.getCurrencyInstance().format(tip)
}
- Dans la fonction TipTimeLayout(), mettez à jour l'appel de fonctioncalculateTip(), puis transmettez un paramètreroundUp:
val tip = calculateTip(amount, tipPercent, roundUp)
- Exécutez l'application. Comme vous pouvez le constater sur les images suivantes, le montant du pourboire est arrondi :
| 
 | 
 | 
7. Ajouter la prise en charge du mode Paysage
Les appareils Android sont disponibles dans différents facteurs de forme (téléphones, tablettes, appareils pliables et appareils ChromeOS) et proposent un large choix quant à la taille de l'écran. Votre application doit être compatible avec les modes Portrait et Paysage.
- Testez votre application en mode Paysage. Activez la rotation automatique.

- Faites pivoter l'émulateur ou l'appareil vers la gauche. Le montant du pourboire n'est plus visible. Pour résoudre ce problème, vous avez besoin d'une barre de défilement verticale afin de faire défiler l'écran de votre application.

- Ajoutez .verticalScroll(rememberScrollState())au modificateur pour ajouter la colonne permettant le défilement vertical de l'écran.rememberScrollState()crée et mémorise automatiquement l'état de défilement.
@Composable
fun TipTimeLayout() {
    // ...
    Column(
        modifier = Modifier
            .padding(40.dp)
            .verticalScroll(rememberScrollState()),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        //...
    }
}
- Exécutez la commande d'importation suivante :
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
- Exécutez à nouveau l'application. Essayez de faire défiler l'écran en mode Paysage.

8. Ajouter une icône précédant les champs de texte (facultatif)
Les icônes peuvent rendre le champ de texte plus attrayant et fournir des informations supplémentaires. Les icônes permettent de transmettre des informations sur l'objectif du champ de texte, comme le type de données attendu ou le type d'entrée requis. Par exemple, l'icône d'un téléphone placée à côté d'un champ de texte peut indiquer que l'utilisateur doit saisir un numéro de téléphone.
Les icônes peuvent faciliter la saisie de l'utilisateur en fournissant des indications visuelles sur l'entrée attendue. Par exemple, une icône représentant un calendrier placée à côté d'un champ de texte peut indiquer que l'utilisateur doit saisir une date.
Vous trouverez ci-dessous un exemple de champ de texte avec une icône de recherche, indiquant que l'utilisateur doit saisir le terme de recherche.

Ajoutez un autre paramètre au composable EditNumberField(), appelé leadingIcon, de type Int. Annotez-le avec @DrawableRes.
@Composable
fun EditNumberField(
    @StringRes label: Int,
    @DrawableRes leadingIcon: Int,
    keyboardOptions: KeyboardOptions,
    value: String,
    onValueChanged: (String) -> Unit,
    modifier: Modifier = Modifier
) 
- Exécutez la commande d'importation suivante :
import androidx.annotation.DrawableRes
import androidx.compose.material3.Icon
- Ajoutez l'icône avant le champ de texte. leadingIconaccepte un composable. Transmettez le composableIconsuivant ;
TextField(
    value = value,
    leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) },
    //...
)
- Transmettez l'icône précédant le texte aux champs de texte. Pour plus de commodité, les icônes sont déjà présentes dans le code de démarrage.
EditNumberField(
    label = R.string.bill_amount,
    leadingIcon = R.drawable.money,
    // Other arguments
)
EditNumberField(
    label = R.string.how_was_the_service,
    leadingIcon = R.drawable.percent,
    // Other arguments
)
- Exécutez l'application.

Félicitations ! Votre application peut à présent calculer des pourboires personnalisés.
9. Télécharger le code de solution
Pour télécharger le code de l'atelier de programmation terminé, utilisez la commande Git suivante :
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git
Vous pouvez également télécharger le dépôt sous forme de fichier ZIP, le décompresser et l'ouvrir dans Android Studio.
Si vous souhaitez voir le code de solution, affichez-le sur GitHub.
10. Conclusion
Félicitations ! Vous avez ajouté une fonctionnalité de pourboire personnalisée à l'application Tip Time. Votre application permet maintenant aux utilisateurs de saisir un pourcentage de pourboire personnalisé et d'arrondir le montant du pourboire. Partagez le fruit de vos efforts sur les réseaux sociaux avec le hashtag #AndroidBasics.
 
  






