Style et Thématisation
Le système de thème Flutter
Flutter utilise un système de thème centralisé pour définir l'apparence globale de l'application. Cela permet de maintenir une cohérence visuelle et de faciliter les changements de design.
ThemeData : Configuration du thème
Définir un thème global
Le thème global est défini dans le widget MaterialApp :
final colorScheme = ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
);
MaterialApp(
title: 'Mon Application',
theme: ThemeData(
// Couleurs principales
primaryColor: Colors.blue,
colorScheme: colorScheme,
brightness: Brightness.light,
// AppBar - Utilise les couleurs du colorScheme
appBarTheme: AppBarTheme(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
elevation: 4,
centerTitle: true,
),
// Boutons élevés
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
// Boutons texte
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
),
),
// Champs de texte
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
),
labelStyle: TextStyle(color: Colors.grey),
),
// Cartes
cardTheme: CardTheme(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
// Typographie
textTheme: const TextTheme(
displayLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
displayMedium: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
bodyLarge: TextStyle(fontSize: 16),
bodyMedium: TextStyle(fontSize: 14),
),
),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.indigo,
),
themeMode: ThemeMode.system, // Suit le thème du système
home: const MyHomePage(),
)
Voir aussi
Voir l'exemple ci-dessus pour comprendre comment :
- Utiliser
colorScheme.primaryetcolorScheme.onPrimarypour synchroniser automatiquement les couleurs de l'AppBar avec le thème général - Personnaliser les boutons, champs de texte, cartes et typographie dans un seul bloc
ThemeData
Utilisation du thème dans les widgets
Accéder au thème
// Dans un widget
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
color: theme.colorScheme.primary,
child: Text(
'Texte stylé',
style: theme.textTheme.displayLarge,
),
);
}
Surcharger le thème localement
Theme(
data: Theme.of(context).copyWith(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
),
child: ElevatedButton(
onPressed: () {},
child: const Text('Bouton rouge'),
),
)
TextStyle : Personnalisation du texte
Styles de texte basiques
Text(
'Texte stylé',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
color: Colors.blue,
letterSpacing: 2,
wordSpacing: 5,
decoration: TextDecoration.underline,
decorationColor: Colors.red,
decorationStyle: TextDecorationStyle.dotted,
),
)
Combinaison de styles
Text(
'Texte avec style combiné',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
)
RichText : Texte avec plusieurs styles
RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: [
const TextSpan(text: 'Texte normal '),
TextSpan(
text: 'texte en gras',
style: const TextStyle(fontWeight: FontWeight.bold),
),
const TextSpan(text: ' et '),
TextSpan(
text: 'texte en couleur',
style: const TextStyle(color: Colors.red),
),
],
),
)
Colors : Gestion des couleurs
Couleurs prédéfinies
Container(color: Colors.blue)
Container(color: Colors.red[500])
Container(color: Colors.amber.shade300)
Couleurs personnalisées
// Couleur ARGB
Container(color: const Color(0xFF2196F3))
// Couleur RGB
Container(color: const Color.fromARGB(255, 33, 150, 243))
// Couleur RGBA
Container(color: const Color.fromRGBO(33, 150, 243, 0.5))
MaterialColor : Palette de couleurs
MaterialColor createMaterialColor(Color color) {
List strengths = <double>[.05];
Map<int, Color> swatch = {};
final int r = color.red, g = color.green, b = color.blue;
for (int i = 1; i < 10; i++) {
strengths.add(0.1 * i);
}
for (var strength in strengths) {
final double ds = 0.5 - strength;
swatch[(strength * 1000).round()] = Color.fromRGBO(
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
1,
);
}
return MaterialColor(color.value, swatch);
}
BoxDecoration : Décoration de Container
Décoration complète
Container(
decoration: BoxDecoration(
// Couleur de fond
color: Colors.blue,
// Dégradé
gradient: const LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
// Bordure
border: Border.all(
color: Colors.black,
width: 2,
),
// Coins arrondis
borderRadius: BorderRadius.circular(12),
// Ombre
boxShadow: const [
BoxShadow(
color: Colors.grey,
blurRadius: 10,
offset: Offset(0, 5),
),
],
// Image de fond
image: const DecorationImage(
image: NetworkImage('https://example.com/image.jpg'),
fit: BoxFit.cover,
),
),
child: const Text('Contenu'),
)
Formes personnalisées
// Cercle
Container(
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
)
// Bordure personnalisée
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.red, width: 3),
bottom: BorderSide(color: Colors.blue, width: 3),
),
),
)
Polices personnalisées
Ajout dans pubspec.yaml
flutter:
fonts:
- family: Roboto
fonts:
- asset: fonts/Roboto-Regular.ttf
- asset: fonts/Roboto-Bold.ttf
weight: 700
Utilisation
Text(
'Texte avec police personnalisée',
style: const TextStyle(
fontFamily: 'Roboto',
fontSize: 20,
),
)
Bonnes pratiques
- Cohérence : Utiliser le thème global plutôt que des valeurs en dur
- Accessibilité : Assurer un bon contraste entre texte et fond
- Responsive : Adapter les tailles de police selon la taille d'écran
- Mode sombre : Toujours prévoir un thème sombre
- ColorScheme : Préférer
ColorSchemeà des couleurs isolées pour une meilleure cohérence
Build Release et Versioning
Après avoir conçu l'interface visuelle, il est temps de préparer l'application pour la distribution.
Préparation du build release
- Mode debug vs mode release (différences de performances et taille)
flutter build apk --releasepour générer un APK optimiséflutter build ios --releasepour générer un IPA optimisé- Taille attendue : 50-150 MB pour les assets de base
Optimisation de la taille
- Utiliser
flutter build apk --target-platform android-arm64pour architecture spécifique - Compresser les images (format WebP plutôt que PNG)
- Supprimer les dépendances inutiles
- Utiliser
flutter pub global run app_size_analyzerpour analyser la taille
Versioning sémantique et gestion des builds
- Mettre à jour
versiondanspubspec.yamlavant chaque release - Format :
major.minor.patch+build - Maintenir un CHANGELOG pour tracker les changements
- Exemple : de
1.0.0+1à1.1.0+2pour une release mineure
Préparation de la métadonnée
- Préparer les icônes de l'app aux bonnes dimensions (192x192, 512x512)
- Composer une description courte et longue pour les stores
- Préparer les screenshots et preview videos
- Écrire les release notes et changelogs