Modales
Introduction
Nylo Website fournit un systeme de modales base sur les modales en feuille inferieure (bottom sheet).
La classe BottomSheetModal vous offre une API flexible pour afficher des superpositions de contenu avec des actions, des en-tetes, des boutons de fermeture et un style personnalise.
Les modales sont utiles pour :
- Les dialogues de confirmation (par exemple, deconnexion, suppression)
- Les formulaires de saisie rapide
- Les feuilles d'actions avec plusieurs options
- Les superpositions informatives
Creer une modale
Vous pouvez creer une nouvelle modale en utilisant le CLI Metro :
metro make:bottom_sheet_modal payment_options
Cela genere deux choses :
- Un widget de contenu de modale dans
lib/resources/widgets/bottom_sheet_modals/modals/payment_options_modal.dart:
import 'package:flutter/material.dart';
/// Payment Options Modal
///
/// Used in BottomSheetModal.showPaymentOptions()
class PaymentOptionsModal extends StatelessWidget {
const PaymentOptionsModal({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('PaymentOptionsModal').headingLarge(),
],
);
}
}
- Une methode statique ajoutee a votre classe
BottomSheetModaldanslib/resources/widgets/bottom_sheet_modals/bottom_sheet_modals.dart:
/// Show Payment Options modal
static Future<void> showPaymentOptions(BuildContext context) {
return displayModal(
context,
isScrollControlled: false,
child: const PaymentOptionsModal(),
);
}
Vous pouvez ensuite afficher la modale depuis n'importe ou :
BottomSheetModal.showPaymentOptions(context);
Si une modale avec le meme nom existe deja, utilisez le flag --force pour l'ecraser :
metro make:bottom_sheet_modal payment_options --force
Utilisation de base
Affichez une modale en utilisant BottomSheetModal :
BottomSheetModal.showLogout(context);
Creer une modale
Le patron recommande est de creer une classe BottomSheetModal avec des methodes statiques pour chaque type de modale. Le code standard fournit cette structure :
import 'package:flutter/material.dart';
import 'package:nylo_framework/nylo_framework.dart';
class BottomSheetModal extends NyBaseModal {
static ModalShowFunction get displayModal => displayModal;
/// Show Logout modal
static Future<void> showLogout(
BuildContext context, {
Function()? onLogoutPressed,
Function()? onCancelPressed,
}) {
return displayModal(
context,
isScrollControlled: false,
child: const LogoutModal(),
actionsRow: [
Button.secondary(
text: "Logout",
onPressed: onLogoutPressed ?? () => routeToInitial(),
),
Button(
text: "Cancel",
onPressed: onCancelPressed ?? () => Navigator.pop(context),
),
],
);
}
}
Appelez-la depuis n'importe ou :
BottomSheetModal.showLogout(context);
// With custom callbacks
BottomSheetModal.showLogout(
context,
onLogoutPressed: () {
// Custom logout logic
},
onCancelPressed: () {
Navigator.pop(context);
},
);
BottomSheetModal
displayModal<T>() est la methode principale pour afficher des modales.
Parametres
| Parametre | Type | Defaut | Description |
|---|---|---|---|
context |
BuildContext |
requis | Contexte de construction pour la modale |
child |
Widget |
requis | Widget de contenu principal |
actionsRow |
List<Widget> |
[] |
Widgets d'action affiches en ligne horizontale |
actionsColumn |
List<Widget> |
[] |
Widgets d'action affiches verticalement |
height |
double? |
null | Hauteur fixe de la modale |
header |
Widget? |
null | Widget d'en-tete en haut |
useSafeArea |
bool |
true |
Envelopper le contenu dans SafeArea |
isScrollControlled |
bool |
false |
Permettre le defilement de la modale |
showCloseButton |
bool |
false |
Afficher un bouton de fermeture X |
headerPadding |
EdgeInsets? |
null | Espacement lorsqu'un en-tete est present |
backgroundColor |
Color? |
null | Couleur de fond de la modale |
showHandle |
bool |
true |
Afficher la poignee de glissement en haut |
closeButtonColor |
Color? |
null | Couleur de fond du bouton de fermeture |
closeButtonIconColor |
Color? |
null | Couleur de l'icone du bouton de fermeture |
modalDecoration |
BoxDecoration? |
null | Decoration personnalisee du conteneur de la modale |
handleColor |
Color? |
null | Couleur de la poignee de glissement |
Actions
Les actions sont des boutons affiches en bas de la modale.
Les actions en ligne sont placees cote a cote, chacune occupant un espace egal :
displayModal(
context,
child: Text("Are you sure?"),
actionsRow: [
ElevatedButton(
onPressed: () => Navigator.pop(context, true),
child: Text("Yes"),
),
TextButton(
onPressed: () => Navigator.pop(context, false),
child: Text("No"),
),
],
);
Les actions en colonne sont empilees verticalement :
displayModal(
context,
child: Text("Choose an option"),
actionsColumn: [
ElevatedButton(
onPressed: () => Navigator.pop(context, true),
child: Text("Yes"),
),
TextButton(
onPressed: () => Navigator.pop(context, false),
child: Text("No"),
),
],
);
En-tete
Ajoutez un en-tete au-dessus du contenu principal :
displayModal(
context,
header: Container(
padding: EdgeInsets.all(16),
color: Colors.blue,
child: Text(
"Modal Title",
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
child: Text("Modal content goes here"),
);
Bouton de fermeture
Affichez un bouton de fermeture dans le coin superieur droit :
displayModal(
context,
showCloseButton: true,
closeButtonColor: Colors.grey.shade200,
closeButtonIconColor: Colors.black,
child: Padding(
padding: EdgeInsets.all(24),
child: Text("Content with close button"),
),
);
Decoration personnalisee
Personnalisez l'apparence du conteneur de la modale :
displayModal(
context,
backgroundColor: Colors.transparent,
modalDecoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [
BoxShadow(color: Colors.black26, blurRadius: 10),
],
),
handleColor: Colors.grey.shade400,
child: Text("Custom styled modal"),
);
BottomModalSheetStyle
BottomModalSheetStyle configure l'apparence des modales en feuille inferieure utilisees par les selecteurs de formulaire et d'autres composants :
BottomModalSheetStyle(
backgroundColor: NyColor(light: Colors.white, dark: Colors.grey.shade900),
barrierColor: NyColor(light: Colors.black54, dark: Colors.black87),
useRootNavigator: false,
titleStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
itemStyle: TextStyle(fontSize: 16),
clearButtonStyle: TextStyle(color: Colors.red),
)
| Propriete | Type | Description |
|---|---|---|
backgroundColor |
NyColor? |
Couleur de fond de la modale |
barrierColor |
NyColor? |
Couleur de la superposition derriere la modale |
useRootNavigator |
bool |
Utiliser le navigateur racine (defaut : false) |
routeSettings |
RouteSettings? |
Parametres de route pour la modale |
titleStyle |
TextStyle? |
Style du texte de titre |
itemStyle |
TextStyle? |
Style du texte des elements de liste |
clearButtonStyle |
TextStyle? |
Style du texte du bouton effacer |
Exemples
Modale de confirmation
static Future<bool?> showConfirm(
BuildContext context, {
required String message,
}) {
return displayModal<bool>(
context,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(message, textAlign: TextAlign.center),
),
actionsRow: [
ElevatedButton(
onPressed: () => Navigator.pop(context, true),
child: Text("Confirm"),
),
TextButton(
onPressed: () => Navigator.pop(context, false),
child: Text("Cancel"),
),
],
);
}
// Usage
bool? confirmed = await BottomSheetModal.showConfirm(
context,
message: "Delete this item?",
);
if (confirmed == true) {
// delete the item
}
Modale avec contenu defilable
displayModal(
context,
isScrollControlled: true,
height: MediaQuery.of(context).size.height * 0.8,
showCloseButton: true,
header: Padding(
padding: EdgeInsets.all(16),
child: Text("Terms of Service", style: TextStyle(fontSize: 20)),
),
child: SingleChildScrollView(
child: Text(longTermsText),
),
);
Feuille d'actions
displayModal(
context,
showHandle: true,
child: Text("Share via", style: TextStyle(fontSize: 18)),
actionsColumn: [
ListTile(
leading: Icon(Icons.email),
title: Text("Email"),
onTap: () {
Navigator.pop(context);
shareViaEmail();
},
),
ListTile(
leading: Icon(Icons.message),
title: Text("Message"),
onTap: () {
Navigator.pop(context);
shareViaMessage();
},
),
ListTile(
leading: Icon(Icons.copy),
title: Text("Copy Link"),
onTap: () {
Navigator.pop(context);
copyLink();
},
),
],
);