Le widget Theme dans Flutter
Le widget Theme dans Flutter
-
Objectifs
- Connaitre la notion thme dans Flutter
- Être capable d’utilisez un thème général pour votre application.
-
Présentation
- Les thèmes sont des packages prédéfinis qui contiennent les apparences graphiques de notre site Web ou de l’écran de notre application mobile. Ils rendent l’interface utilisateur plus attrayante. Nous utilisons principalement des thèmes pour partager les couleurs et les styles de police dans toute l’application.
- Dans le développement mobile, il devient obligatoire d’ajouter le thème clair et sombre pour notre application. Aujourd’hui, la plupart des gens préfèrent la version sombre du thème à la version claire, car elle les rend plus confortables pour leurs yeux et augmente la durée de vie de la batterie.
- Dans Flutter , nous pouvons soit utiliser des widgets de thème qui contiennent les couleurs et les styles de police pour une zone spécifique de l’application, soit définir des thèmes pour l’ensemble de l’application . Les thèmes pour l’ensemble de l’application sont également des widgets de thème, qui sont créés à la racine de notre application sous le widget MaterialApp .
- La plupart des widgets visuels dans Flutter ont une propriété style dont le type varie en fonction du widget. Les exemples incluent TextStyle pour le widget Text ou ButtonStyle pour le widget Button. La spécification d’un style n’affectera que ce widget spécifique.
- Le widget Theme dans Flutter vous permet de définir un thème pour votre application qui contrôle les éléments visuels de l’interface utilisateur de votre application, tels que les couleurs, les styles de texte et les formes. Vous pouvez utiliser le widget Theme pour appliquer un thème à une sous-arborescence spécifique de l’arborescence de widgets de votre application, ou vous pouvez l’utiliser à la racine de votre application pour l’appliquer à l’ensemble de l’application.
-
Propriétés du Widget «
Theme
» en flutter - Le widget «
Theme
» dans Flutter est un moyen puissant de définir l’apparence d’une application en encapsulant les styles et les paramètres de thème dans une arborescence de widgets. Voici un aperçu détaillé des propriétés du widget Theme, ainsi qu’un exemple d’utilisation.: - data: Cette propriété est utilisée pour définir les données de thème pour l’arborescence des widgets. Il prend une instance de ThemeData comme valeur.
- child: Cette propriété spécifie le widget auquel le thème doit être appliqué. Tous les enfants de ce widget hériteront des styles définis dans data.
- shadowThemeOnly:Cette propriété détermine si le thème ne doit s’appliquer qu’aux éléments du thème de l’ombre, comme DropShadow, au lieu de s’appliquer à l’ensemble de l’arborescence des widgets. Cela permet de personnaliser uniquement les ombres sans affecter d’autres styles.
- key: Cette propriété est utilisée pour définir une clé unique pour le widget, ce qui est utile dans les scénarios où vous devez trouver le widget dans l’arborescence des widgets.
-
Exemple:
-
Activité
- Énoncé:
- Utilisez les thèmes définis précédemment dans votre projet pour personnaliser l’apparence de l’écran suivant. Cet écran doit inclure :
- Un AppBar avec un titre stylé conformément au thème.
- Un texte central utilisant un style provenant du textTheme du thème.
- Un bouton positionné en bas de l’écran, stylé selon le thème des boutons.
- Une image
- Instructions :
- Copiez le code contenant le thème si nécessaire.
- Assurez-vous que les widgets de l’écran utilisent les styles configurés dans le thème global (Theme.of(context) ou directement via themeData).
- Affichez un message « Thème appliqué avec succès ! » lorsqu’on appuie sur le bouton.
-
Commençons par choisir les couleurs de notre application.
-
Personnaliser votre thème
- Nous sommes dans une application de type Material, cela implique donc de définir au moins deux couleurs :
PrimaryColor
etSecondaryColor
. - La couleur primaire sera celle de votre barre de navigation.
- La couleur secondaire sera la couleur d’accent, par exemple, la couleur de votre bouton flottant (FloatingActionButton).
- Une fois ces deux couleurs choisies, il nous faut une déclinaison
light
etdark
de ces couleurs. Vous pouvez les définir vous même, ou bien utiliser cet outil qui les génèrera pour vous. -
appliquer votre thème
- Maintenant que votre thème est prêt, il est temps de le porter fièrement. Enveloppez votre application dans le widget MaterialApp et transmettez votre objet ThemeData au themeparamètre, comme suit :
-
Application
- Objectif de l’Exercice
- Créer une application Flutter qui permet à l’utilisateur de choisir entre différents thèmes (par exemple, un thème « Fête », un thème « Nature », et un thème « Minimaliste ») à l’aide d’une interface utilisateur simple.
- Étapes à Suivre
- Créer une Application Flutter de Base
- Définir Plusieurs Thèmes
- Implémenter un Menu pour Changer de Thème
- Appliquer le Thème Choisi à l’Application
- Étape 1 : Créer une Application Flutter de Base
- Commencez par créer une nouvelle application Flutter :
- Étape 2 : Définir Plusieurs Thèmes
- Modifiez votre fichier lib/main.dart pour y inclure plusieurs thèmes :
- Étape 3 : Implémenter un Menu pour Changer de Thème
- Créez un écran d’accueil qui permet à l’utilisateur de sélectionner un thème :
- Étape 4 : Appliquer le Thème Choisi à l’Application
- Dans cet exemple, chaque bouton appelle _changeTheme avec un thème spécifique lorsque l’utilisateur le sélectionne.
- Résultat Attendu
- Lorsque vous exécutez cette application, vous devriez voir un écran avec un titre et trois boutons. En cliquant sur chaque bouton, le thème de l’application doit changer immédiatement pour refléter le thème sélectionné.
- Améliorations Possibles
- Ajouter des Images de Fond : Personnalisez chaque thème avec une image de fond différente.
- Animations de Transition : Ajoutez des animations lors du changement de thème pour une expérience utilisateur plus fluide.
- Stockage des Préférences de Thème : Utilisez SharedPreferences pour mémoriser le choix de thème de l’utilisateur entre les sessions.
// theme.dart
import 'package:flutter/material.dart';
final ThemeData themeData = ThemeData(
primaryColor: Colors.teal,
colorScheme: const ColorScheme.light(
secondary: Colors.blueAccent,
),
textTheme: const TextTheme(
bodyLarge: TextStyle(color: Colors.black, fontSize: 18),
titleLarge: TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold),
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.white, backgroundColor: Colors.teal,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, backgroundColor: Colors.teal,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
);
Remarque : Le widget «
Theme
» ne peut être utilisé qu’une seule fois dans une arborescence de widgets. Si vous souhaitez appliquer le même thème à plusieurs widgets, vous devez envelopper chaque arborescence de widgets avec le widget Theme et transmettre la même instance ThemeData à chacun.
Solution
import 'package:flutter/material.dart';
import 'mes_themes.dart'; // Assurez-vous d'importer votre thème
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: themeData, // Applique le thème défini dans theme.dart
home: Scaffold(
backgroundColor: Colors.teal[50], // Fond doux pour l'écran
appBar: AppBar(
title: Text('Exemple de widget de thème'),
centerTitle: true, // Centrer le titre
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center, // Centrer horizontalement
children: [
// Premier texte avec style du thème
Text(
"Ce texte utilisera le style bodyLarge du thème.",
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
SizedBox(height: 30), // Espacement
// Container avec la couleur primaire
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(12),
boxShadow: [
// Ombre pour effet 3D
BoxShadow(
color: Colors.black26,
blurRadius: 6,
offset: Offset(0, 4),
),
],
),
child: Text(
"Ce conteneur utilise la couleur primaire.",
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
),
SizedBox(height: 30),
// TextButton avec le style du thème
// le style du TextButton est automatiquement appliqué grâce à la configuration dans votre fichier mes_themes.dart, où vous avez défini un style global pour tous les TextButton via le widget TextButtonThemeData.
TextButton(
onPressed: () {},
// Afficher le SnackBar
child: const Text("Cliquez-moi"),
),
const SizedBox(height: 30),
// ElevatedButton avec le style du thème
ElevatedButton(
onPressed: () {},
child: const Text("Bouton Elevé"),
),
SizedBox(height: 30),
// Card avec image et texte
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 5,
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Stack(
children: [
Image.network(
'https://via.placeholder.com/150',
width: 150,
height: 150,
fit: BoxFit.cover,
),
Positioned(
bottom: 16,
left: 16,
child: Text(
"Image de la Card",
style: Theme.of(context).textTheme.titleLarge,
),
),
],
),
),
),
SizedBox(height: 30),
// ListTile avec thème
ListTile(
leading: Icon(Icons.home, color: Colors.teal),
title: Text("Item 1",
style: Theme.of(context).textTheme.bodyLarge),
subtitle: Text("Description de l'item 1",
style: Theme.of(context).textTheme.bodyLarge),
tileColor: Colors.teal[100],
),
SizedBox(height: 10),
ListTile(
leading: Icon(Icons.business, color: Colors.teal),
title: Text("Item 2",
style: Theme.of(context).textTheme.bodyLarge),
subtitle: Text("Description de l'item 2",
style: Theme.of(context).textTheme.bodyLarge),
tileColor: Colors.teal[100],
),
],
),
),
),
),
),
);
}
}
final ThemeData myAwesomeTheme = ThemeData(
primaryColor: Colors.lime,
accentColor: Colors.orange,
fontFamily: 'Roboto',
);
MaterialApp(
theme: myAwesomeTheme,
home: MyHomePage(),
);