Material Dialog : c’est quoi et comment l’utiliser ? - Tuto Android

Material Dialog : c’est quoi et comment l’utiliser ? - Tuto Android
Victor COLEAUMis à jour le 14 Oct 2021
material dialog définition

Material Dialog, à quoi ça sert ?

Marre de créer des Dialog sous AndroidAndroid est un système d'exploitation mobile basé sur Linux. ? Marre de devoir utiliser des DialogFragment et autre AlertDialog ? Marre de devoir créer une nouvelle classe pour chaque fenêtre, et de devoir le refaire pour chaque projet ? Grâce à Material Dialog, vous n'aurez plus jamais à utiliser les classes de base d'Android et pourrez créer vos fenêtres modales en quelques lignes seulement. 

full.png

Installation de Material Dialog

Très simple, il vous suffit d'ajouter une dépendance dans votre fichier Gradle :

dependencies {
    ...
    implementation 'com.afollestad.material-dialogs:core:3.2.1'
}

Utilisation de Material Dialog

Créer une première fenêtre

Pour créer votre toute première fenêtre, seules quelques lignes suffisent :

MaterialDialog(this).show {
  title(R.string.title)
  message(R.string.message)
  icon(R.drawable.icon)
}

Et c'est tout ! 

basic.png

Dans cet exemple, this doit être une Activity. La méthode show, comme son nom l'indique, affiche directement la pop-up dès sa création, et permet de définir tout un tas d'attributs dont nous voyons les trois premiers ici : title, message et icon. Chacun étant optionnel.

Si vous ne vouliez pas utiliser de ressources mais plutôt passer directement un string littéral ou une variable, il vous faut dans ce cas utiliser un argument nommé :

MaterialDialog(this).show {
  title(text = "Votre titre")
  message(text = "Votre message")
  icon(R.drawable.icon)
}

Enfin, plutôt que d'utiliser la méthode show pour afficher la fenêtre au moment de sa déclaration, vous pouvez stocker votre objet MaterialDialog dans une variable et appeler sa méthode show plus tard :

val dialog = MaterialDialog(this)
  .title(R.string.title)
  .message(R.string.message)
  .icon(R.drawable.icon)
  
dialog.show()

Cela vous permet notamment d'utiliser plusieurs fois la même dialog si besoin. Vous pouvez aussi appeler la méthode dismiss qui fermera manuellement une pop-up ouverte.

dialog.dismiss()

Ajouter des boutons

Là encore, tout est simplifié grâce à Material Dialog et en une seule méthode, vous pouvez ajouter un bouton à votre pop-up.

MaterialDialog(this).show {
  positiveButton(R.string.agree) { dialog ->
    // Action au click
  }
  negativeButton(R.string.disagree) { dialog ->
    // Action au click
  }
}

Rien de plus à faire, les boutons sont automatiquement créés et positionnés. Vous n'avez qu'à remplir le corps des callback pour définir ce que doit faire votre application en réponse à un clic.

Les listes

Plusieurs types de listes sont à votre disposition : liste simple, choix simple ou choix multiple.

Liste simple 
basic_list.png

Pour afficher une liste d'objets dans votre pop-up, un seul attribut est à rajouter : listItems. Celui-ci peut utiliser une ressource array ou une variable prédéfinie.

MaterialDialog(this).show {
  listItems(R.array.items) { dialog, index, text ->
    // dialog: référence à la pop-up
    // index: indice de l'item cliqué
    // text: texte de l'item cliqué
  }
}
val myItems = listOf("Hello", "World")

MaterialDialog(this).show {
  listItems(items = myItems)
}

La méthode de callback permet de définir la comportement de l'application lorsqu'un item de la liste est cliqué.

Choix simple 
single_choice_list.png

Tout comme pour une liste simple, un seul attribut permet de créer une liste à choix unique pour votre pop-up : listItemsSingleChoice.

Deux arguments en plus sont disponibles :

  • initialSelection [int] : définit quel item est pré-sélectionné - optionnel.
  • disabledIndices [array(int)] : définit quels items ne sont pas sélectionnables - optionnel.

La méthode de callback permet de définir la comportement de l'application lorsqu'un item de la liste est cliqué/sélectionné.

val indices = intArrayOf(0, 2)

MaterialDialog(this).show {
  listItemsSingleChoice(R.array.items, initialSelection = 1, disabledIndices = indices) { dialog, index, text ->
    // dialog: référence à la pop-up
    // index: indice de l'item cliqué/sélectionné
    // text: texte de l'item cliqué/sélectionné
  }
}

NOTE Par défaut, le clic sur un item ferme la pop-up. Si vous ajoutez un positiveButton, la fermeture sera alors activée uniquement par le clic sur le bouton.

Enfin, plusieurs méthodes sont à votre disposition pour manipuler l'état des items.

dialog.checkItem(index) // Sélectionne l'item à l'indice donné
dialog.uncheckItem(index) // Désélectionne l'item à l'indice donné
dialog.toggleItemChecked(index) // Inverse la sélection de l'item à l'indice donné

val checked: Boolean = dialog.isItemChecked(index) // Indique si l'item à l'indice donné est sélectionné

Choix multiple 
multi_choice_list.png

Là aussi, un seul attribut gère tout : listItemsMultiChoice.

val initialIndices = intArrayOf(1, 3)
val disableIndices = intArrayOf();

MaterialDialog(this).show {
  listItemsMultiChoice(R.array.items, initialSelection = initialIndices, disabledIndices = disableIndices) { dialog, indices, items ->
    // dialog: référence à la pop-up
    // indices: indice des items cliqués/sélectionnés
    // items: texte des items cliqués/sélectionnés
  }
}

Les méthodes à votre disposition pour manipuler l'état des items sont :

dialog.checkItems(indices) // Sélectionne les items aux indices donnés
dialog.uncheckItems(indices) // Désélectionne les items aux indices donnés
dialog.toggleItemsChecked(indices) // Inverse la sélection des items aux indices donnés
dialog.checkAllItems() // Sélectionne tous les items
dialog.uncheckAllItems() // Désélectionne tous les items
dialog.toggleAllItemsChecked() // Inverse la sélection de tous les items
val checked: Boolean = dialog.isItemChecked(index) // Indique si l'item à l'indice donné est sélectionné

Case à cocher 
checkbox.png

Material Dialog permet aussi d'ajouter une case à cocher dans votre pop-up. Pour cela, ajoutez l'attribut checkBoxPrompt. Celui-ci demande un label et a une méthode de callback appelée à chaque fois que la case est cochée/décochée.

MaterialDialog(this).show {
  checkBoxPrompt(R.string.label) { checked ->
      // checked: état de la case
  }
}

Attention ! Le callback est appelé à CHAQUE fois que la case est cochée/décochée mais n'intervient pas dans le processus de validation. Pour cela, vérifiez l'état de la case dans le callback du bouton.

MaterialDialog(this).show {
  checkBoxPrompt(R.string.label)
  positiveButton(R.string.button) { dialog ->
      val isChecked = dialog.isCheckPromptChecked()
      // Action au click
  }
}

Text Input

Une autre utilisation possible d'une pop-up est le renseignement d'un champ de texte. 

input.png

Dépendance

Il vous faut tout d'abord ajouter une seconde dépendance.

dependencies {
    ...
    implementation 'com.afollestad.material-dialogs:core:3.2.1'
    implementation 'com.afollestad.material-dialogs:input:3.3.0'
}

Utilisation

Ensuite, l'ajout de l'attribut input suffit. Le champ de texte est automatiquement créé et positionné dans la pop-up. Celui-ci possède cinq arguments possibles et un callback :

  • waitForPositiveButton [boolean] : si mis à false, le callback est appelé à chaque fois que le texte est modifié. Sinon, uniquement lors de la validation.
  • allowEmpty [boolean] : autorise ou non un texte vide.
  • hintRes [ressource texte] / hint [string] : défini le placeholder
  • prefillRes [ressource texte] / prefill [string] : défini le texte déjà présent à la création de la pop-up. Utile pour modifier un texte existant par exemple.
  • maxLength [int] : défini le nombre maximal de caractères.
MaterialDialog(this).show {
  input(waitForPositiveButton =true, allowEmpty = true, hint = "Placeholder", prefill = "Modifier ce texte", maxLength = 50) { dialog, text ->
      // dialog: référence à la pop-up
      // text: texte entré par l'utilisateur
  }
}

Date et Time

Material Dialog offre aussi la possibilité d'entrer une date, un horaire ou les deux.

Dépendance

Là aussi, il vous faudra d'abord ajouter une seconde dépendance.

dependencies {
    ...
    implementation 'com.afollestad.material-dialogs:core:3.2.1'
    implementation 'com.afollestad.material-dialogs:datetime:3.2.1'
}

Date

Le simple ajout de l'attribut datePicker transforme la pop-up en sélecteur de date. 

datepicker.png

En plus du callback permettant de gérer les actions à réaliser une fois une date choisie, trois arguments optionnels sont disponibles pour préciser votre requête :

  • minDate : Date minimale. Aucune date avant celle-ci ne pourra être sélectionnée.
  • maxDate : Date maximale. Aucune date après celle-ci ne pourra être sélectionnée.
  • currentDate : Date pré-sélectionnée. Utile pour édition.
MaterialDialog(this).show {
  datePicker { dialog, date ->
    // dialog: référence à la pop-up
    // date: date choisie
  }
}

Time 
timepicker.png

De la même façon, l'attribut timePicker transforme la pop-up en sélecteur d'une heure.

En plus du callback permettant de gérer les actions à réaliser une fois une heure choisie, deux arguments optionnels sont disponibles pour préciser votre requête :

  • currentTime : Date pré-sélectionnée. Utile pour édition.
  • show24HoursView : si true, affiche une horloge à 24 heures.
MaterialDialog(this).show {
  timePicker { dialog, time ->
    // dialog: référence à la pop-up
    // time: heure choisie
  }
}

DateTime

L'attribut DateTime comme son nom l'indique est une combinaison de Date et Time

datetimepicker.png

Il s'utilise de la même façon que les précédents et affichera à la suite un écran de sélection d'une date, puis un écran de sélection d'une heure.

Cinq arguments sont disponibles :

  • minDateTime : Date et heure minimales. Aucune date avant celle-ci ne pourra être sélectionnée.
  • maxDateTime : Date et heure maximales. Aucune date après celle-ci ne pourra être sélectionnée.
  • currentDateTime : Date et heure pré-sélectionnées. Utile pour édition.
  • show24HoursView : si true, affiche une horloge à 24 heures.
  • requireFutureDateTime : force l'utilisateur à sélectionner une date future.
MaterialDialog(this).show {
  ...
  dateTimePicker(requireFutureDateTime = true, etc.) { dialog, dateTime ->
    // dialog: référence à la pop-up
    // time: date et heure choisies
  }
  positiveButton(R.string.button)
}

Fichiers et dossiers

Une autre extension permet de créer un sélecteur de fichiers ou de dossiers.

Dépendance

Ce module nécessite une dépendance en plus du core.

dependencies {
    ...
    implementation 'com.afollestad.material-dialogs:core:3.2.1'
    implementation 'com.afollestad.material-dialogs:files:3.2.1'
}

NOTE Pour utiliser ce module, votre application a besoin de la permission READ_EXTERNAL_STORAGE. Dans le cas contraire, la page sera vide.

Gestion de fichiers

Pour transformer la pop-up en sélecteur de fichiers, il suffit d'utiliser l'attribut fileChooser

file_chooser.png

Celui-ci peut prendre en paramètres plusieurs arguments, tous optionnels :

  • initialDirectory [File] : défini le dossier de base dans lequel pointera le sélecteur.
  • filter [Condition] : filtre les fichiers qui seront visibles.
  • emptyText [string] / emptyTextRes [ressource texte] : si une dossier est vide, label par défaut.
  • allowFolderCreation [boolean] : autorise la création de dossier.
  • folderCreationLabel [ressource texte] : texte du bouton de création de dossier.
MaterialDialog(this).show {
  fileChooser(initialDirectory = initialFolder, etc.) { dialog, file ->
    // dialog: référence à la pop-up
    // file: fichier choisi
  }
  positiveButton(R.string.button)
}

NOTE Si un bouton de validation est défini, cliquer sur un fichier n'appelera pas le callback mais ne fera que le sélectionner. Le callback ne sera appelé uniquement à la validation.

Gestion de dossiers 
file_chooser.png

La gestion de dossiers est très similaire à celle des fichiers. Les principales différences sont :

  • seuls les dossiers sont affichés.
  • cliquer sur un dossier n'appelle jamais le callback, seul le bouton valider le fait.

L'attribut utilisé est folderChooser. Les arguments possibles restent les mêmes que pour fileChooser.

MaterialDialog(this).show {
  folderChooser(initialDirectory = initialFolder, etc.) { dialog, folder ->
    // dialog: référence à la pop-up
    // folder: dossier choisi
  }
  positiveButton(R.string.button)
}

Couleurs

Enfin, MaterialDialog propose un module pour choisir une couleur.

Dépendance

La dépendance à utiliser est la suivante :

dependencies {
    ...
    implementation 'com.afollestad.material-dialogs:core:3.2.1'
    implementation 'com.afollestad.material-dialogs:color:3.2.1'
}

Utilisation

L'attribut colorChooser transforme votre pop-up en sélecteur de couleurs. 

color_chooser.png

Trois arguments sont possibles :

  • colors [tableau de int] : liste des couleurs parmi lesquels l'utilisateur peut choisir.
  • subColors [tableau de tableau de int] : liste de listes de nuances d'une couleur. Attention : ce tableau doit être de même taille que colors.
  • initialSelection [int] : couleur pré-sélectionnée.
val colors = intArrayOf(RED, GREEN, BLUE)

val subColors = listOf(
  intArrayOf(LIGHT_RED, RED, DARK_RED, WHITE),
  intArrayOf(LIGHT_GREEN, GREEN, DARK_GREEN, GRAY),
  intArrayOf(LIGHT_BLUE, BLUE, DARK_BLUE, BLACK)
)

MaterialDialog(this).show {
  title(R.string.colors)
  colorChooser(colors, subColors = subColors, initialSelection = BLUE) { dialog, color ->
    // dialog: référence à la pop-up
    // color: couleur choisie
  }
  positiveButton(R.string.button)
}

Il est aussi possible d'intégrer un sélecteur de RGB grâce au paramètre allowCustomArgb [boolean]. Dans ce cas, le paramètre showAlphaSelector [boolean] permet de cacher ou non le sélecteur de transparence. 

custom_argb.png

val colors = intArrayOf(RED, GREEN, BLUE)

val subColors = listOf(
  intArrayOf(LIGHT_RED, RED, DARK_RED, WHITE),
  intArrayOf(LIGHT_GREEN, GREEN, DARK_GREEN, GRAY),
  intArrayOf(LIGHT_BLUE, BLUE, DARK_BLUE, BLACK)
)

MaterialDialog(this).show {
  title(R.string.colors)
  colorChooser(
    colors,
    subColors = subColors,
    allowCustomArgb = true,
    showAlphaSelector = true
  ) { dialog, color ->
    // dialog: référence à la pop-up
    // color: couleur choisie
  }
  positiveButton(R.string.button)
}

Conclusion

MaterialDialog offre encore de nombreuses possibilités que vous pouvez découvrir sur la documentation officielle : https://github.com/afollestad/material-dialogs.

Sa versatilité, sa souplesse et sa facilité d'utilisation sont autant d'avantages qui font de MaterialDialog une des librairies les plus utiles et pratiques pour tous vos développements Android. Une fois que vous l'aurez essayée, vous ne voudrez plus jamais créer de pop-up à la main ! 

full.png