4.5Dialogs, SnackBar et BottomSheet dans Flutter
4.5.1 – Principes de feedback utilisateur
Le feedback utilisateur est essentiel pour une bonne expérience. Il permet à l'utilisateur de comprendre ce qui se passe dans l'application.
đź’¬ Pourquoi donner du feedback ?
Quand un utilisateur effectue une action, il doit savoir :
- Si l'action a réussi ou échoué
- Ce qui se passe actuellement (chargement, traitement...)
- Quelles sont les prochaines étapes possibles
Si l'utilisateur clique sur "Supprimer", il doit savoir si la suppression a réussi. Sans feedback, l'utilisateur ne sait pas si son action a été prise en compte, ce qui crée de la confusion et de la frustration.
📊 Types de feedback
Flutter propose plusieurs moyens de communiquer avec l'utilisateur :
- Dialog : Message important qui bloque l'interface jusqu'à ce que l'utilisateur réponde
- SnackBar : Notification discrète en bas de l'écran qui disparaît automatiquement
- BottomSheet : Panneau qui glisse depuis le bas pour afficher des options ou des informations
🎯 Quand utiliser chaque composant ?
Utilisez un Dialog pour :
- Demander une confirmation avant une action importante (suppression, déconnexion...)
- Afficher une erreur critique qui nécessite l'attention de l'utilisateur
- Demander des informations essentielles
Utilisez une SnackBar pour :
- Confirmer une action réussie ("Message envoyé", "Données sauvegardées")
- Afficher une information non critique
- Informer d'un changement d'état
Utilisez un BottomSheet pour :
- Afficher des options d'action (partager, modifier, supprimer...)
- Montrer des informations supplémentaires sans changer d'écran
- Proposer plusieurs choix Ă l'utilisateur
💡 Règle d'or
Choisissez le bon composant selon l'importance du message :
- Critique → Dialog (l'utilisateur doit absolument voir et répondre)
- Information → SnackBar (l'utilisateur peut continuer sans interagir)
- Options → BottomSheet (l'utilisateur choisit parmi plusieurs actions)
4.5.2 – Dialogs
Un Dialog est une fenêtre modale qui s'affiche au-dessus de l'interface et bloque l'interaction jusqu'à ce que l'utilisateur réponde.
📝 Syntaxe
Voici comment afficher un Dialog :
// Afficher un Dialog
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Titre du Dialog'),
content: const Text('Message du Dialog'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
),
],
);
},
);
// Fermer un Dialog
Navigator.pop(context);
// Fermer un Dialog et retourner une valeur
Navigator.pop(context, 'valeur');
Analysons cette syntaxe :
showDialog(): Fonction qui affiche un Dialogcontext: Le contexte de l'application (nécessaire pour afficher le Dialog)builder: Fonction qui construit le DialogAlertDialog: Widget qui crée un Dialog avec titre, contenu et actionstitle: Le titre du Dialog (optionnel)content: Le contenu principal du Dialogactions: Liste des boutons d'action (généralement en bas du Dialog)Navigator.pop(context): Ferme le DialogNavigator.pop(context, valeur): Ferme le Dialog et retourne une valeur
Le paramètre
context est nécessaire pour que Flutter sache où afficher le Dialog dans l'arbre des widgets. Vous l'obtenez automatiquement dans la méthode build().
đź§Ş Exemple : Dialog simple
Voici un exemple complet qui affiche un Dialog simple :
showDialog() pour afficher un Dialog simple.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dialogs'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Titre du Dialog'),
content: const Text('Message du Dialog'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
),
],
);
},
);
},
child: const Text('Afficher un Dialog'),
),
),
),
);
}
}
Dans cet exemple :
- Un bouton affiche un Dialog quand on clique dessus
- Le Dialog contient un titre, un message et un bouton "OK"
- Quand on clique sur "OK", le Dialog se ferme avec
Navigator.pop(context)
âś… Dialog de confirmation
Un Dialog de confirmation permet de demander à l'utilisateur de confirmer une action avant de l'exécuter.
📝 Syntaxe
Voici la syntaxe pour un Dialog de confirmation :
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Confirmer la suppression'),
content: const Text('Êtes-vous sûr de vouloir supprimer cet élément ?'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context); // Annuler
},
child: const Text('Annuler'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context); // Fermer le Dialog
// Exécuter l'action ici
},
child: const Text('Supprimer'),
),
],
);
},
);
La seule vraie différence est l’ajout d’un
ElevatedButton pour l’action “Supprimer”.Dans un dialog simple, il n’y avait qu’un seul bouton “OK”. Ici :
- On garde le bouton “Annuler” (avec
TextButton, une alternative fréquente à un bouton “OK”). - On ajoute un bouton Supprimer (avec
ElevatedButton) qui permet de déclencher l’action de confirmation (par exemple, supprimer l’élément).
ElevatedButton (pour la confirmation) qui distingue ce Dialog de confirmation d’un dialog simple à un seul bouton.
đź§Ş Exemple : Dialog de confirmation
Voici un exemple complet avec un bouton qui affiche un Dialog de confirmation :
showDialog() pour afficher un Dialog de confirmation.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Confirmation'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Confirmer la suppression'),
content: const Text('Êtes-vous sûr de vouloir supprimer cet élément ?'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context); // Annuler
},
child: const Text('Annuler'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context); // Fermer le Dialog
// Ici, vous pouvez exécuter l'action de suppression
print('Élément supprimé');
},
child: const Text('Supprimer'),
),
],
);
},
);
},
child: const Text('Supprimer'),
),
),
),
);
}
}
Dans cet exemple :
- Le Dialog propose deux actions : "Annuler" et "Supprimer"
- Si l'utilisateur clique sur "Annuler", le Dialog se ferme sans rien faire
- Si l'utilisateur clique sur "Supprimer", le Dialog se ferme et l'action est exécutée
- L'utilisateur doit choisir avant de continuer
📝 Dialog avec retour de valeur
Un Dialog peut retourner une valeur quand il est fermé, permettant à l'écran qui l'a ouvert de savoir quelle action l'utilisateur a choisie.
📝 Syntaxe
Voici la syntaxe pour un Dialog qui retourne une valeur :
// Afficher un Dialog et attendre le résultat
final resultat = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Choisir une option'),
content: const Text('Que voulez-vous faire ?'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context, 'option1'); // Retourner 'option1'
},
child: const Text('Option 1'),
),
TextButton(
onPressed: () {
Navigator.pop(context, 'option2'); // Retourner 'option2'
},
child: const Text('Option 2'),
),
],
);
},
);
// Utiliser le résultat
if (resultat != null) {
print('L\'utilisateur a choisi : $resultat');
}
Analysons cette syntaxe :
await showDialog(): Attend que le Dialog soit ferméNavigator.pop(context, 'option1'): Ferme le Dialog et retourne une valeurresultat: Contient la valeur retournée (ounullsi fermé sans valeur)
Le deuxième paramètre de
Navigator.pop() est la valeur retournée. Si l'utilisateur ferme le Dialog en cliquant en dehors ou en appuyant sur retour, resultat sera null.
đź§Ş Exemple : Dialog avec retour de valeur
Voici un exemple complet oĂą un Dialog retourne le choix de l'utilisateur :
showDialog() pour afficher un Dialog avec retour de valeur.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String? choixUtilisateur;
Future<void> afficherDialogAvecRetour() async {
final resultat = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Choisir une option'),
content: const Text('Que voulez-vous faire ?'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context, 'option1'); // Retourner 'option1'
},
child: const Text('Option 1'),
),
TextButton(
onPressed: () {
Navigator.pop(context, 'option2'); // Retourner 'option2'
},
child: const Text('Option 2'),
),
],
);
},
);
if (resultat != null) {
setState(() {
choixUtilisateur = resultat as String;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Dialog avec retour'),
),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: afficherDialogAvecRetour,
child: const Text('Afficher le Dialog'),
),
if (choixUtilisateur != null) ...[
const SizedBox(height: 20),
Text(
'Vous avez choisi : $choixUtilisateur',
style: const TextStyle(fontSize: 18),
),
],
],
),
),
),
);
}
}
Dans cet exemple :
- Le bouton affiche un Dialog avec deux options
- Chaque option retourne une valeur différente avec
Navigator.pop(context, valeur) - La valeur retournée est stockée dans
choixUtilisateuret affichée à l'écran - Si l'utilisateur ferme le Dialog sans choisir,
resultatseranull
⚠️ Dialog d'erreur
void afficherErreur(String message) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Erreur'),
content: Text(message),
actions: [
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
),
],
);
},
);
}
Un Dialog d'erreur informe l'utilisateur qu'un problème s'est produit.
💡 Points clés à retenir
- Un Dialog bloque l'interface jusqu'à ce que l'utilisateur réponde
- Utilisez
showDialog()pour afficher un Dialog AlertDialogest le widget de base pour créer un Dialog- Utilisez
Navigator.pop(context)pour fermer le Dialog - Un Dialog peut retourner une valeur avec
Navigator.pop(context, valeur) - Utilisez les Dialogs pour les messages importants qui nécessitent une réponse
4.5.3 – SnackBar
Une SnackBar est une notification discrète qui s'affiche en bas de l'écran et disparaît automatiquement après quelques secondes.
📝 Syntaxe
Voici comment afficher une SnackBar :
// Afficher une SnackBar simple
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Message affiché dans la SnackBar'),
),
);
// SnackBar avec durée personnalisée
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Message personnalisé'),
duration: const Duration(seconds: 5),
),
);
// SnackBar avec action
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Élément supprimé'),
action: SnackBarAction(
label: 'Annuler',
onPressed: () {
// Action à exécuter
},
),
),
);
// SnackBar avec couleur personnalisée
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Message d\'erreur'),
backgroundColor: Colors.red,
),
);
Analysons cette syntaxe :
ScaffoldMessenger.of(context): Obtient le gestionnaire de SnackBarshowSnackBar(): Affiche la SnackBarSnackBar: Widget qui crée la notificationcontent: Le contenu de la SnackBar (généralement unText)duration: Durée d'affichage (par défaut 4 secondes)action: Bouton d'action optionnelbackgroundColor: Couleur de fond de la SnackBar
ScaffoldMessenger est le système qui gère l'affichage des SnackBar dans Flutter. Il est automatiquement disponible dans un Scaffold. Vous devez utiliser ScaffoldMessenger.of(context) pour obtenir son instance.
đź§Ş Exemple : SnackBar simple
Voici un exemple complet qui affiche une SnackBar simple :
ScaffoldMessenger.of(context).showSnackBar() pour afficher une SnackBar simple.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SnackBar'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Message affiché dans la SnackBar'),
),
);
},
child: const Text('Afficher une SnackBar'),
),
),
),
);
}
}
Dans cet exemple :
- Un bouton affiche une SnackBar quand on clique dessus
- La SnackBar s'affiche en bas de l'écran avec le message
- La SnackBar disparaît automatiquement après 4 secondes
ScaffoldMessenger est le système qui gère l'affichage des SnackBar dans Flutter. Il est automatiquement disponible dans un Scaffold. Vous devez utiliser ScaffoldMessenger.of(context) pour obtenir son instance.
⏱️ SnackBar avec durée personnalisée
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Message personnalisé'),
duration: const Duration(seconds: 5), // Afficher pendant 5 secondes
),
);
Par défaut, une SnackBar disparaît après 4 secondes. Vous pouvez changer cette durée avec le paramètre duration.
🎨 SnackBar avec action
Une SnackBar peut contenir un bouton d'action :
ScaffoldMessenger.of(context).showSnackBar() pour afficher une SnackBar avec action.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Élément supprimé'),
action: SnackBarAction(
label: 'Annuler',
onPressed: () {
print('Action annulée');
// Ici, vous pouvez annuler l'action précédente
},
),
),
);
Analysons ce code :
action: Paramètre qui ajoute un bouton d'actionSnackBarAction: Widget qui crée le bouton d'actionlabel: Le texte du boutononPressed: Action à exécuter quand le bouton est pressé
âś… SnackBar de confirmation
ScaffoldMessenger.of(context).showSnackBar() pour afficher une SnackBar avec background.
ElevatedButton(
onPressed: () {
// Exécuter une action
print('Action effectuée');
// Afficher une confirmation
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Action réussie !'),
backgroundColor: Colors.green,
),
);
},
child: const Text('Effectuer une action'),
)
Une SnackBar de confirmation informe l'utilisateur qu'une action a réussi. Vous pouvez changer la couleur avec backgroundColor.
❌ SnackBar d'erreur
void afficherErreurSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
);
}
Une SnackBar d'erreur utilise généralement une couleur rouge pour attirer l'attention.
💡 Points clés à retenir
- Une SnackBar est une notification discrète qui ne bloque pas l'interface
- Utilisez
ScaffoldMessenger.of(context).showSnackBar()pour afficher une SnackBar - Une SnackBar disparaît automatiquement après quelques secondes (4 secondes par défaut)
- Vous pouvez ajouter une action avec le paramètre
action - Utilisez les SnackBar pour les messages non critiques qui ne nécessitent pas d'interaction
- Changez la couleur avec
backgroundColorpour indiquer le type de message
- SnackBar : Message informatif, disparaît automatiquement, ne bloque pas
- Dialog : Message important, nécessite une réponse, bloque l'interface
4.5.4 – BottomSheet
Un BottomSheet est un panneau qui glisse depuis le bas de l'écran pour afficher des options ou des informations supplémentaires.
📝 Syntaxe
Voici comment afficher un BottomSheet :
// BottomSheet modal (bloque l'interface)
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: const Text('Contenu du BottomSheet'),
);
},
);
// BottomSheet avec hauteur personnalisée
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
height: 300, // Hauteur fixe
padding: const EdgeInsets.all(20),
child: const Text('Contenu du BottomSheet'),
);
},
);
// BottomSheet avec coins arrondis
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
builder: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: const Text('BottomSheet avec coins arrondis'),
);
},
);
// Fermer un BottomSheet
Navigator.pop(context);
Analysons cette syntaxe :
showModalBottomSheet(): Affiche un BottomSheet modal (bloque l'interface)context: Le contexte de l'application (nécessaire pour afficher le BottomSheet)builder: Fonction qui construit le contenu du BottomSheetheight: Hauteur fixe du BottomSheet (optionnel)shape: Forme personnalisée du BottomSheet (pour arrondir les coins)Navigator.pop(context): Ferme le BottomSheet
showModalBottomSheet() affiche un BottomSheet qui bloque l'interface. L'utilisateur doit fermer le BottomSheet (en glissant vers le bas ou en appuyant sur retour) avant de pouvoir continuer à interagir avec le reste de l'application. C'est la méthode recommandée pour afficher des options ou des actions importantes.
đź§Ş Exemple : BottomSheet simple
Voici un exemple complet qui affiche un BottomSheet simple :
showModalBottomSheet() pour afficher un BottomSheet simple.
import 'package:flutter/material.dart';
void main() {
runApp(const MaPage());
}
class MaPage extends StatelessWidget {
const MaPage({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomSheet'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: const Text('Contenu du BottomSheet'),
);
},
);
},
child: const Text('Afficher un BottomSheet'),
),
),
),
);
}
}
Dans cet exemple :
- Un bouton affiche un BottomSheet quand on clique dessus
- Le BottomSheet glisse depuis le bas de l'écran
- Le BottomSheet contient un texte simple dans un Container
- L'utilisateur peut fermer le BottomSheet en glissant vers le bas ou en appuyant sur retour
📝 BottomSheet avec options
Un BottomSheet est souvent utilisé pour afficher des options d'action :
showModalBottomSheet() pour afficher un BottomSheet avec options.
void afficherOptions() {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.share),
title: const Text('Partager'),
onTap: () {
Navigator.pop(context);
print('Partager');
},
),
ListTile(
leading: const Icon(Icons.edit),
title: const Text('Modifier'),
onTap: () {
Navigator.pop(context);
print('Modifier');
},
),
ListTile(
leading: const Icon(Icons.delete),
title: const Text('Supprimer'),
onTap: () {
Navigator.pop(context);
print('Supprimer');
},
),
],
),
);
},
);
}
Analysons ce code :
Column: Organise les options verticalementmainAxisSize: MainAxisSize.min: La colonne prend seulement l'espace nécessaireListTile: Widget qui crée une ligne avec icône, titre et actionleading: Widget affiché au début (généralement une icône)onTap: Action à exécuter quand la ligne est pressée
📏 BottomSheet avec hauteur personnalisée
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
height: 300, // Hauteur fixe
padding: const EdgeInsets.all(20),
child: const Text('Contenu du BottomSheet'),
);
},
);
Vous pouvez définir une hauteur fixe avec height, ou laisser le BottomSheet s'adapter au contenu.
🎨 BottomSheet arrondi
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
builder: (context) {
return Container(
padding: const EdgeInsets.all(20),
child: const Text('BottomSheet avec coins arrondis'),
);
},
);
Le paramètre shape permet de personnaliser la forme du BottomSheet, notamment pour arrondir les coins supérieurs.
💡 Points clés à retenir
- Un BottomSheet glisse depuis le bas de l'écran
- Utilisez
showModalBottomSheet()pour un BottomSheet modal - Le BottomSheet peut contenir n'importe quel widget
- Utilisez
ListTilepour créer des listes d'options - Fermez le BottomSheet avec
Navigator.pop(context) - Utilisez les BottomSheet pour afficher des options ou des informations supplémentaires
- Personnalisez la forme avec
shapeet la hauteur avecheight
4.5.5 – Choisir le bon composant de feedback
Choisir le bon composant selon la situation est essentiel pour une bonne expérience utilisateur.
📊 Tableau comparatif
| Composant | Quand l'utiliser | Bloque l'interface ? | Disparaît automatiquement ? |
|---|---|---|---|
Dialog |
Confirmation, erreur critique, demande d'information importante | Oui | Non |
SnackBar |
Confirmation d'action, information non critique | Non | Oui (4 secondes) |
BottomSheet |
Options d'action, informations supplémentaires | Oui (modal) ou Non | Non |
🎯 Exemples d'utilisation
- Dialog : "Êtes-vous sûr de vouloir supprimer ?" (demande de confirmation)
- SnackBar : "Élément supprimé" (confirmation après suppression)
- BottomSheet : Afficher les options (Partager sur Facebook, Twitter, Email...)
- SnackBar : "Contenu partagé" (confirmation après partage)
- Dialog : "Erreur de connexion. Vérifiez votre connexion Internet." (erreur critique)
- SnackBar : "Connexion perdue" (information non bloquante)
âś… Bonnes pratiques
- Ne pas abuser des Dialogs : Ils bloquent l'interface, utilisez-les seulement pour les cas importants
- Utiliser les SnackBar pour les confirmations : Elles sont discrètes et n'interrompent pas le flux
- BottomSheet pour les options : Idéal pour afficher plusieurs choix sans changer d'écran
- Messages clairs et concis : L'utilisateur doit comprendre rapidement le message
- Cohérence : Utilisez toujours le même type de composant pour le même type de message
💡 Règle de décision rapide
- L'utilisateur doit absolument répondre ? → Dialog
- Je veux juste informer l'utilisateur ? → SnackBar
- Je veux proposer plusieurs options ? → BottomSheet
Choisissez le composant selon l'importance et le type de message :
- Dialog = Important, nécessite une réponse
- SnackBar = Information, discrète
- BottomSheet = Options, choix multiples
Vous avez terminé ce chapitre ! Vous savez maintenant :
- âś… Quand et comment utiliser les Dialogs
- ✅ Afficher des notifications discrètes avec les SnackBar
- âś… Proposer des options avec les BottomSheet
- âś… Choisir le bon composant selon la situation