MODULE 3 - TRAVAILLER AVEC FLUTTER
Processus de développement des applications Flutter
1. 📌 Planification et conception
Définir les besoins de l’application (fonctionnalités, public cible,
plateformes visées).
Créer des maquettes (wireframes) et prototypes UI/UX.
Choisir l’architecture (par ex. MVVM, Clean Architecture).
2. ⚙️ Configuration de l’environnement
Installer le SDK Flutter et Dart.
Configurer un IDE (VS Code, Android Studio).
Vérifier les émulateurs/simulateurs pour Android et iOS.
3. � Développement
Créer la structure du projet avec flutter create.
Développer les interfaces avec widgets (stateless et stateful).
Gérer l’état avec des solutions comme Provider, Riverpod, Bloc ou GetX.
Intégrer des packages (ex. http pour les requêtes réseau, intl pour la
localisation).
4. 🔗 Intégration backend et API
Consommer des services REST ou GraphQL.
Gérer la persistance des données (SQLite, Hive, Firebase).
Implémenter l’authentification et la sécurité.
5. � Tests et qualité
Tests unitaires (logique métier).
Tests widget (interface).
Tests d’intégration (flux complet).
Vérification des performances et optimisation.
6. 📱 Compilation et déploiement
Générer des builds pour Android (.apk ou .aab) et iOS (.ipa).
Publier sur Google Play Store et Apple App Store.
Configurer CI/CD pour automatiser les builds et déploiements.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
7. 🔄 Maintenance et mises à jour
Corriger les bugs.
Ajouter de nouvelles fonctionnalités.
Suivre les retours utilisateurs et améliorer l’expérience.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Widgets Flutter
Définition : Un widget est une classe qui décrit une partie de l’UI.
Types principaux :
StatelessWidget : immuable, ne change pas après sa création (ex. Text,
Icon).
StatefulWidget : peut évoluer en fonction d’un état interne ou externe
(ex. Checkbox, TextField).
Flutter propose un vaste catalogue de widgets, regroupés en plusieurs familles
Catégorie Exemples Utilité
Éléments fondamentaux
Base widgets Text, Container, Row, Column
pour construire l’UI
Material Scaffold, AppBar, Respectent les guidelines
widgets FloatingActionButton Material Design (Android)
Cupertino CupertinoButton, Respectent les guidelines
widgets CupertinoNavigationBar iOS
Layout Organisation et disposition
Stack, GridView, ListView
widgets des éléments
Input & Saisie et interaction
TextField, Slider, Switch
interaction utilisateur
Animation &
AnimatedContainer, Hero Effets visuels et transitions
Motion
Créer une application Flutter
Flutter
📂 Structure des dossiers
mon_projet/
│
├── android/ → Code et configuration spécifiques à Android (Gradle,
Manifest, etc.)
├── ios/ → Code et configuration spécifiques à iOS (Xcode, [Link],
etc.)
├── lib/ → Dossier principal du code Dart (toute la logique de l’app)
│ └── [Link] → Point d’entrée de l’application
│
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
├── test/ → Tests unitaires et widgets
├── web/ → Fichiers spécifiques pour le déploiement web (si activé)
├── build/ → Fichiers générés automatiquement (ne pas modifier)
│
├── [Link] → Fichier de configuration (dépendances, assets, fonts,
version, etc.)
├── [Link] → Verrouillage des versions des dépendances
├── analysis_options.yaml → Règles de lint/analyse statique (optionnel)
1. lib/
C’est le cœur de votre application :
[Link] : point d’entrée (void main() => runApp(MyApp());).
Vous pouvez organiser en sous-dossiers :
o screens/ → pages de l’application.
o widgets/ → composants réutilisables.
o models/ → classes de données.
o services/ → logique métier, API, base de données.
o utils/ → fonctions utilitaires.
o providers/ ou bloc/ → gestion d’état.
2. [Link]
Déclare les dépendances (http, intl, provider, etc.).
Déclare les assets (images, JSON, etc.) :
flutter:
assets:
- assets/images/
- assets/data/
fonts:
- family: Roboto
fonts:
- asset: assets/fonts/[Link]
3. android/ et ios/
Contiennent le code natif et la configuration pour chaque plateforme.
Vous n’avez pas besoin d’y toucher souvent, sauf pour :
o Ajouter des permissions (ex. accès internet, caméra).
o Intégrer des SDK natifs.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
4. test/
Contient vos tests unitaires et de widgets.
Exemple :
import 'package:flutter_test/flutter_test.dart';
void main() {
test('Exemple de test', () {
expect(2 + 2, 4);
});
}
Organisation recommandée dans lib/
lib/
├── [Link]
├── screens/
│ ├── home_screen.dart
│ └── login_screen.dart
├── widgets/
│ ├── custom_button.dart
│ └── input_field.dart
├── models/
│ └── [Link]
├── services/
│ └── api_service.dart
├── utils/
│ └── [Link]
└── state/
└── app_provider.dart
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Le Widget en Flutter
Un widget en Flutter est l’élément de base qui compose toute l’interface
utilisateur. Chaque bouton, texte, image ou mise en page est un widget.
Flutter repose sur une hiérarchie de widgets (appelée widget tree) qui décrit l’UI
et son comportement.
StatelessWidget
Ne dépend pas d’un état interne.
Exemple : Text, Icon.
Utilisé pour des éléments statiques ou constants.
StatefulWidget
Possède un état mutable qui peut évoluer.
Exemple : Checkbox, TextField.
Utilisé pour des composants interactifs.
Catégories de widgets
Base widgets : Container, Row, Column, Stack.
Material widgets : Scaffold, AppBar, FloatingActionButton (design
Android).
Cupertino widgets : CupertinoButton, CupertinoNavigationBar (design
iOS).
Layout widgets : ListView, GridView.
Input & interaction : TextField, Slider, Switch.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Animation : AnimatedContainer, Hero.
- Affichage du Text au centre
void main(){
runApp(
Center(
child: Text(
"Hello, flutter",
textDirection: [Link],
),
)
);
}
- Image au centre
runApp(
Center(
child:
[Link]("[Link]
9wzNzgHaFj?cb=ucfimgc2&rs=1&pid=ImgDetMain&o=7&rm=3")
)
);
Stateless Widget
void main(){
runApp(const HomePage());
class HomePage extends StatelessWidget{
const HomePage({[Link]});
@override
Widget build(BuildContext context){
return const Center(
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
child: Text(
"Home Page",
textDirection: [Link],
),
);
}
}
Material Design
void main(){
runApp(const MaterialApp(
home : HomePage()
));
}
- Scaffold
class HomePage extends StatelessWidget{
const HomePage({[Link]});
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(title : Text("Apli"), elevation: 12,),
body : Center(child: Text("Bonjour"),),
floatingActionButton: FloatingActionButton(
onPressed: (){},
child: Icon([Link]),
),
);
}
}
- STATEFUL
//STATEFUL
class HomePage extends StatefulWidget{
const HomePage({[Link]});
@override
State<HomePage> createState(){
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
return HomePageState();
}
}
class HomePageState extends State<HomePage>{
int counter = 0;
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(title : Text("Apli"), elevation: 12,),
body : Center(child: Text("Bonjour $counter"),),
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
counter +=1;
});
},
child: Icon([Link]),
),
);
}
}
Container
Rôle principal
Encapsulation : Il peut contenir un autre widget (texte, image, bouton,
etc.).
Mise en forme : Permet de définir la taille, les marges, les paddings.
Décoration : Ajout de couleurs, bordures, coins arrondis, ombres.
Transformation : Rotation, translation ou mise à l’échelle.
Propriétés courantes
child : le widget contenu.
padding : espace interne.
margin : espace externe.
height / width : dimensions fixes.
alignment : positionnement du contenu.
decoration : personnalisation (couleur, bordure, gradient, etc.).
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Container(
height: 100,
width: 200,
padding: [Link](20),
margin: [Link](20),
alignment: [Link],
decoration: BoxDecoration(
color: [Link],
borderRadius: [Link](15),
boxShadow: [
BoxShadow(
color: [Link],
blurRadius: 4,
offset: Offset(2, 2)
)
]
),
child: [Link]("[Link]
feature_png-maker-image_hero_mobile.jpg"),
)
Column
Caractéristiques principales
Orientation : horizontale.
Propriété clé : children → une liste de widgets à afficher côte à côte.
Contrôle de l’espace :
o mainAxisAlignment → aligne les enfants sur l’axe principal
(horizontal).
o crossAxisAlignment → aligne les enfants sur l’axe transversal
(vertical).
Flexibilité : peut-être combiné avec Expanded ou Flexible pour gérer la
répartition de l’espace.
Column(
mainAxisAlignment: [Link],
crossAxisAlignment: [Link],
children: [
Icon([Link], size: 40, color: [Link],),
Text(
'Hello Column!',
style: TextStyle(fontSize: 20),
),
ElevatedButton(
onPressed: () {},
child: Text('Click'),
),
],
)
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Row
Propriétés principales
children : liste des widgets à afficher côte à côte.
mainAxisAlignment : contrôle l’alignement horizontal (axe principal).
o Exemples : start, center, end, spaceBetween, spaceAround,
spaceEvenly.
crossAxisAlignment : contrôle l’alignement vertical (axe transversal).
o Exemples : start, center, end, stretch.
mainAxisSize : définit si la ligne prend tout l’espace ([Link])
ou seulement ce qui est nécessaire ([Link]).
Row(
mainAxisAlignment: [Link],
crossAxisAlignment: [Link],
children: [
Icon([Link], size: 40, color: [Link]),
Text(
'Accueil',
style: TextStyle(fontSize: 20),
),
ElevatedButton(
onPressed: () {},
child: Text('Entrer'),
),
],
)
ListView
Caractéristiques principales
Défilement vertical par défaut (mais peut être horizontal).
Optimisé pour les grandes listes : ne rend que les éléments visibles à
l’écran.
Flexible : peut contenir n’importe quel widget comme enfant.
Contrôle du défilement : via scrollDirection, controller, etc.
ListView simple Fournit une liste de widgets directement via children.
children: <Widget>[
ListTile(title: Text('Élément 1')),
ListTile(title: Text('Élément 2')),
ListTile(title: Text('Élément 3')),
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
],
);
[Link] Génère les éléments à la demande, idéal pour les grandes
listes.
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
leading: Icon([Link]),
title: Text('Élément ${index + 1}'),
);
},
);
[Link] Ajoute un séparateur entre les éléments.
[Link](
itemCount: 10,
itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
separatorBuilder: (context, index) => Divider(),
);
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Navigation Bar
- Créations de 04 pages discussions – actus –
//IMPORTATIONS DES PAGES
import 'package:flutter_tp/pages/[Link]';
import 'package:flutter_tp/pages/[Link]';
import 'package:flutter_tp/pages/[Link]';
import 'package:flutter_tp/pages/[Link]';
import 'package:flutter/[Link]';
class ActusPage extends StatelessWidget{
@override
Widget build(BuildContext context){
return Center(
child: Text("Actus page !"),
);
}
}
void main(){
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
runApp(MaterialApp(
theme: ThemeData(
colorSchemeSeed: [Link],
scaffoldBackgroundColor: [Link]
),
home : HomePage()
));
}
class HomePage extends StatefulWidget{
const HomePage({[Link]});
@override
State<HomePage> createState()=> HomePageState();
}
class HomePageState extends State<HomePage>{
final pages = [
DiscussionsPage(),
ActusPage(),
CommunautesPage(),
AppelsPage()
];
int pageIndex = 0;
@override
Widget build(BuildContext context){
return Scaffold(
body: pages[pageIndex],
bottomNavigationBar: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: [Link], width: 0.2)
)
),
child: NavigationBar(
selectedIndex: pageIndex,
onDestinationSelected: (int index){
setState(() {
pageIndex = index;
});
},
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
backgroundColor: [Link],
destinations: [
NavigationDestination(
icon: Icon([Link]),
label: "Discussions"
),
NavigationDestination(
icon: Icon(Icons.filter_tilt_shift),
label: "Actus"
),
NavigationDestination(
icon: Icon([Link]),
label: "Communautés"
),
NavigationDestination(
icon: Icon([Link]),
label: "Appels"
),
]
),
)
);
}
}
Buttons
Types de boutons en Flutter
ElevatedButton
o Bouton avec un effet d’élévation (ombre).
o Idéal pour mettre en avant une action principale.
TextButton
o Bouton plat, sans ombre.
o Utilisé pour des actions secondaires ou discrètes.
OutlinedButton
o Bouton avec une bordure.
o Convient pour des actions alternatives ou moins prioritaires.
IconButton
o Bouton contenant uniquement une icône.
o Parfait pour les barres d’outils ou actions rapides.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
FloatingActionButton (FAB)
o Bouton circulaire flottant.
o Utilisé pour l’action principale d’un écran (ex. ajouter un élément).
Color bgColor = [Link];
@override
Widget build(BuildContext context){
return Scaffold(
backgroundColor: bgColor,
body: ListView(
children: [
ElevatedButton(
onPressed: (){
setState(() {
bgColor = [Link];
});
},
child: Text("ElevatedButton"),
style: [Link](
backgroundColor: [Link],
),
),
OutlinedButton(
onPressed: (){},
child: Text("OutlinedButton")
),
TextButton(
onPressed: (){},
child: Text("TextButton")
),
IconButton(
onPressed: (){},
icon: Icon([Link]),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: (){},
child: Icon([Link]),
),
);
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
AppBar
AppBar est un widget Flutter qui représente la barre d’application en haut
de l’écran.
Scaffold pour afficher un titre, des
actions (icônes/boutons), et parfois un menu ou un onglet.
l’équivalent de la barre de navigation dans une application mobile.
Propriétés principales
title : le texte ou widget affiché au centre.
actions : liste de widgets (souvent des IconButton) placés à droite.
leading : widget placé à gauche (par défaut, un bouton retour si
navigation).
backgroundColor : couleur de fond.
centerTitle : booléen pour centrer le titre (utile sur Android).
elevation : ombre portée sous l’AppBar.
class MyAppBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Mon AppBar"),
centerTitle: true,
backgroundColor: [Link],
elevation: 4,
leading: Icon([Link]), // icône à gauche
actions: [
IconButton(
icon: Icon([Link]),
onPressed: () {
print("Recherche cliquée !");
},
),
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () {
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
print("Menu cliqué !");
},
),
],
),
body: Center(child: Text("Contenu principal")),
);
}
Menu Drawer
Drawer est un panneau latéral qui s’ouvre depuis le bord gauche (ou
droit) de l’écran.
menu de navigation dans une application.
Scaffold, via la propriété drawer.
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
backgroundColor: [Link](context).[Link],
title: Text("Mon Appli"),
elevation: 18.0,
actions: [
IconButton(
onPressed: (){},
icon: Icon([Link])
),
IconButton(
onPressed: (){},
icon: Icon(Icons.more_vert)
),
],
),
body: Center(
child: Text("Flutter"),
)
);
drawer: Drawer(
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
child: ListView(
children: [
DrawerHeader(
decoration: BoxDecoration(
color: [Link]
),
child: Text("Menu")
),
ListTile(
leading: Icon([Link]),
title: Text("Parametre"),
subtitle: Text("Mon sous parametre"),
trailing: Icon(Icons.chevron_right),
onTap: (){},
),
ListTile(
leading: Icon(Icons.account_box),
title: Text("Profil"),
onTap: (){},
),
ListTile(
leading: Icon([Link]),
title: Text("Help"),
onTap: (){},
),
ListTile(
leading: Icon([Link]),
title: Text("Quittez"),
onTap: (){},
),
],
),
),
Exemple 2
class MyDrawerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Demo Drawer")),
drawer: Drawer(
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
child: ListView(
padding: [Link],
children: [
DrawerHeader(
decoration: BoxDecoration(color: [Link]),
child: Text(
"Menu Principal",
style: TextStyle(color: [Link], fontSize: 24),
),
),
ListTile(
leading: Icon([Link]),
title: Text("Accueil"),
onTap: () {
[Link](context); // Ferme le Drawer
print("Accueil sélectionné");
},
),
ListTile(
leading: Icon([Link]),
title: Text("Paramètres"),
onTap: () {
[Link](context);
print("Paramètres sélectionnés");
},
),
ListTile(
leading: Icon([Link]),
title: Text("Déconnexion"),
onTap: () {
[Link](context);
print("Déconnexion sélectionnée");
},
),
],
),
),
body: Center(child: Text("Contenu principal")),
);
}
}
Personnalisation
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
DrawerHeader : tu peux y mettre une image, un logo, ou un profil
utilisateur.
ListTile : parfait pour les éléments du menu.
UserAccountsDrawerHeader : widget pratique pour afficher un profil
avec photo, nom et email.
drawer: Drawer(
child: ListView(
children: [
UserAccountsDrawerHeader(
accountName: Text("Prince"),
accountEmail: Text("prince@[Link]"),
currentAccountPicture: CircleAvatar(
backgroundImage: AssetImage("assets/[Link]"),
),
),
ListTile(
leading: Icon([Link]),
title: Text("Dashboard"),
onTap: () {},
),
],
),
),
Les bases de la navigation en Flutter
1. Navigation impérative (Navigator)
Flutter utilise une pile (stack) pour gérer les écrans :
[Link]() → ajoute un nouvel écran au-dessus de la pile.
[Link]() → enlève l’écran du dessus et retourne au précédent.
// Aller vers une nouvelle page
[Link](
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
// Revenir en arrière
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
[Link](context);
2. Navigation nommée (Named Routes)
Pratique pour les applis avec plusieurs écrans. On définit les routes dans
MaterialApp.
void main() {
runApp(MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/second': (context) => SecondPage(),
},
));
}
// Navigation
[Link](context, '/second');
// Retour
[Link](context);
3. Passage de données entre pages
On peut transmettre des arguments lors de la navigation :
[Link](
context,
MaterialPageRoute(
builder: (context) => DetailPage(data: "Bonjour Prince"),
),
);
Et dans DetailPage :
class DetailPage extends StatelessWidget {
final String data;
DetailPage({required [Link]});
@override
Widget build(BuildContext context) {
return Text(data);
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
}
}
4. Navigation moderne avec go_router
Flutter recommande aujourd’hui go_router pour simplifier le routage, surtout
avec Flutter Web et les applis complexes.
Flutter pub add go_router
dependencies:
flutter:
sdk: flutter
go_router: ^14.2.0
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomePage(),
),
GoRoute(
path: '/detail/:id',
builder: (context, state) {
final id = [Link]['id'];
return DetailPage(id: id!);
},
),
],
);
void main() {
runApp([Link](
routerConfig: _router,
));
}
Atelier : Mini-app avec 3 écrans
Objectif : Construire une application Flutter avec trois pages (Accueil →
Détails → Paramètres) et pratiquer différentes méthodes de navigation.
Étape 1 : Créer la structure de base
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
import 'package:flutter/[Link]';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/details': (context) => DetailsPage(),
'/settings': (context) => SettingsPage(),
},
);
}
}
Étape 2 : Écran d’accueil (HomePage)
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Accueil")),
body: Center(
child: Column(
mainAxisAlignment: [Link],
children: [
ElevatedButton(
onPressed: () {
[Link](context, '/details', arguments: "Message
depuis Accueil");
},
child: Text("Aller vers Détails"),
),
ElevatedButton(
onPressed: () {
[Link](context, '/settings');
},
child: Text("Aller vers Paramètres"),
),
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
],
),
),
);
}
}
Étape 3 : Écran de détails (DetailsPage)
class DetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final args = [Link](context)!.[Link] as String?;
return Scaffold(
appBar: AppBar(title: Text("Détails")),
body: Center(
child: Column(
mainAxisAlignment: [Link],
children: [
Text(args ?? "Pas de données reçues"),
ElevatedButton(
onPressed: () {
[Link](context);
},
child: Text("Retour"),
),
],
),
),
);
}
}
Étape 4 : Écran des paramètres (SettingsPage)
class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Paramètres")),
body: Center(
child: ElevatedButton(
onPressed: () {
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
[Link](context);
},
child: Text("Retour"),
),
),
);
}
}
Exercice 1 : Ajouter un bouton sur la page Détails qui envoie un nouveau
message vers Paramètres.
Exercice 2 : Modifier la navigation pour utiliser MaterialPageRoute au lieu
des routes nommées.
Exercice 3 : Refaire la même mini-app avec go_router pour comparer la
simplicité.
TextField
1. TextField simple
TextField(
decoration: InputDecoration(
labelText: "Nom",
hintText: "Entrez votre nom",
border: OutlineInputBorder(),
),
)
labelText → texte affiché au-dessus du champ.
hintText → texte indicatif à l’intérieur du champ.
border → personnalisation de la bordure.
2. Contrôler le texte avec TextEditingController
final TextEditingController _controller = TextEditingController();
TextField(
controller: _controller,
decoration: InputDecoration(labelText: "Email"),
)
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
// Récupérer la valeur
String email = _controller.text;
Indispensable pour lire ou modifier le contenu du champ.
3. Options utiles
keyboardType: [Link] → clavier adapté (email,
numérique, etc.).
obscureText: true → masquer le texte (mot de passe).
maxLength: 20 → limite de caractères.
onChanged: (value) { print(value); } → écoute en temps réel.
onSubmitted: (value) { print("Entré: $value"); } → action après
validation.
Atelier : Formulaire de connexion
Étape 1 : Créer un Form avec une clé globale
final _formKey = GlobalKey<FormState>();
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
body: Padding(
padding: [Link](16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: "Email"),
controller: emailController,
keyboardType: [Link],
validator: (value){
if(value == null || [Link]){
return "Veuillez entrer votre email";
}
if(){
return "Veuillez entrer un email valide";
}
return null;
},
),
TextFormField(
decoration: InputDecoration(labelText: "Password"),
controller: passwordController,
obscureText: true,
validator: (value){
if(value == null || [Link]){
return "Veuillez entrer votre mot de passe";
}
return null;
},
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
),
ElevatedButton(
onPressed: (){
if(_formKey.currentState!.validate()){
print("Email : ${[Link]}");
print("Password : ${[Link]}");
[Link](context).showSnackBar(
SnackBar(content: Text("Connexion réussie"))
);
}
},
child: Text("Se connecter"),
)
],
)
)
),
Points clés
Form + GlobalKey<FormState> → permet de gérer la validation
globale.
TextFormField → intègre directement la validation via validator.
ScaffoldMessenger → affiche des messages de feedback (SnackBar).
Contrôleurs (TextEditingController) → récupèrent les valeurs saisies.
Exercice 1 : Ajouter un champ "Nom d’utilisateur" obligatoire.
Exercice 2 : Créer un bouton "Réinitialiser" qui vide tous les champs
([Link]()).
Exercice 3 : Ajouter une validation personnalisée (ex. mot de passe doit
contenir un chiffre).
Exercice 4 : Transformer ce formulaire en formulaire d’inscription avec 3
champs (nom, email, mot de passe).
Exercice bonus : Utiliser onSaved pour stocker les valeurs dans un objet User.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Lab : Créer une mise en page dans Flutter avec la navigation
Objectifs
Après avoir terminé ce laboratoire, vous serez en mesure de :
Construire une mise en page de base dans Flutter en utilisant des
widgets comme Column, Row, Container et Text
Implémenter la navigation entre plusieurs écrans en
utilisant Navigator et Routes
Utiliser des widgets Flutter courants pour créer une mise en page
visuellement attrayante et réactive
Comprendre et gérer l’état au sein d’une application Flutter
Améliorer les mises en page avec des éléments interactifs tels que des
champs de texte et la validation de formulaires
Termes clés
Widget : Le bloc de construction de base de l’interface utilisateur de
l’application Flutter. Tout dans Flutter est un widget.
Mise en page : Comment les éléments visuels sont disposés dans une
application.
Navigateur : Un widget qui gère une pile d’objets de route et fournit des
méthodes pour naviguer entre les routes.
Route : Une abstraction pour un écran ou une page dans une application
Flutter.
Formulaire : Un groupe de champs de saisie avec une logique de
validation.
Étape 1 : Construire une mise en page de base
Supprimez tout le code de [Link]. Vous allez repartir de zéro.
- Importez le package [Link] :
import 'package:flutter/[Link]';
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
- Définissez la fonction principale d’entrée :
void main(){
runApp(const MyApp());
}
Créez un widget sans état nommé MyApp :
class MyApp extends StatelessWidget{
const MyApp({[Link]})
}
MyApp est un widget personnalisé qui étend StatelessWidget, utilisé
lorsque le widget ne gère aucun état propre.
Le constructeur const est utilisé ici pour indiquer que MyApp est
immuable.
Surchargez la méthode build pour définir la structure de l’application :
@override
Widget build(BuildContext context){
// Espace réservé pour les propriétés de MaterialApp
}
La méthode build décrit comment afficher le widget dans l’application.
Le paramètre context fournit des informations sur l’emplacement de ce
widget dans l’arbre des widgets.
Ajoutez le widget MaterialApp à la méthode build pour commencer à
construire l’application :
@override
Widget build(BuildContext context){
return MaterialApp(
title: 'Laboratoire de mise en page Flutter',
// Espace réservé pour la propriété home
);
}
MaterialApp est un widget pratique qui enveloppe plusieurs widgets
couramment utilisés pour concevoir une application material.
Définissez la propriété home avec un widget Scaffold :
return MaterialApp(
title: 'Laboratoire de mise en page Flutter',
home: Scaffold(
),
);
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Scaffold fournit un cadre qui implémente la structure de mise en page de
base du design material de l’interface visuelle.
Ajoutez un widget AppBar au Scaffold :
home: Scaffold(
appBar: AppBar(
title: const Text('Exemple de mise en page Flutter'),
),
// Espace réservé pour le corps
),
AppBar est une barre d’application de design material qui peut être
utilisée pour donner à l’application un aspect et une sensation cohérents
en haut de l’écran.
title est une propriété pour ajouter du texte à la barre d’application.
Définissez le body du Scaffold en utilisant un widget Column :
body: const Column(
children: const <Widget>[
Text('Bienvenue dans Flutter !'),
Text('Construire une mise en page est facile.'),
],
),
Column est un widget de mise en page qui arrange ses enfants dans une
direction verticale.
La propriété children prend une liste de widgets à afficher.
Les widgets Text affichent du texte à l’écran.
Étape 2 : Exécuter l'application
Étape 3 : Améliorer la mise en page avec plus de widgets
Mettez à jour le fichier [Link] pour ajouter un widget Row à l’intérieur de
la Column :
body: const Column(
children: const <Widget>[
Row(
// Espace réservé pour les propriétés et enfants de Row
),
Text('Bienvenue dans Flutter !'),
Text('Construire une mise en page est facile.'),
],
),
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Row est un widget de mise en page qui arrange ses enfants dans une
direction horizontale.
Ajoutez mainAxisAlignment pour contrôler l’alignement dans le Row :
Row(
mainAxisAlignment: [Link],
// Espace réservé pour les propriétés et enfants de Row
),
mainAxisAlignment définit comment les enfants doivent être placés le
long de l’axe principal (horizontal).
Ajoutez des widgets enfants au Row :
Row(
mainAxisAlignment: [Link],
children: const<Widget>[
Icon([Link], color: [Link]),
Icon([Link], color: [Link]),
Icon(Icons.thumb_up, color: [Link]),
],
),
Le widget Icon est utilisé pour afficher des icônes.
[Link], [Link] et Icons.thumb_up sont des icônes prédéfinies
dans Flutter.
Étape 4 : Mise en page avancée avec interactions, journalisation et
formulaires
Mettez à jour le fichier [Link] pour inclure le paquet logger
Installez le paquet logger en exécutant la commande suivante dans votre terminal : flutter pub
add logger
Le paquet logger fournit un utilitaire de journalisation simple pour
imprimer des messages de journal.
Initialisez le Logger dans l’état de votre MyForm :
import 'package:logger/[Link]'; // Importez le paquet logger
import 'package:flutter/[Link]';
import 'package:logger/[Link]'; // Importez le paquet logger
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({[Link]});
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Layout Lab',
home: Scaffold(
appBar: AppBar(
title: const Text('Exemple de mise en page Flutter'),
),
body: MyForm(),
),
);
}
}
class MyForm extends StatefulWidget {
@override
_MyFormState createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
final Logger _logger = Logger(); // Initialisez le logger
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
const Row(
mainAxisAlignment: [Link],
children: const<Widget>[
Icon([Link], color: [Link]),
Icon([Link], color: [Link]),
Icon(Icons.thumb_up, color: [Link]),
],
),
const Text('Bienvenue dans Flutter !'),
const Text('Construire une mise en page est facile.'),
TextFormField(
decoration: const InputDecoration(labelText: 'Entrez votre
nom'),
validator: (value) {
if (value == null || [Link]) {
return 'Veuillez entrer un texte';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_logger.i('Le formulaire est valide. L\'entrée de
l\'utilisateur est enregistrée.'); // Journalisez l'entrée de l'utilisateur
}
},
child: const Text('Soumettre'),
),
],
),
);
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
}
}
o Logger est utilisé pour imprimer un message de journal lorsque le
formulaire est valide et que le bouton est pressé.
Comme nous utilisons un script spécial pour exécuter l’application, le logger ne
peut pas enregistrer dans le terminal. Au lieu de cela, ajoutons une fonction
pour afficher une boîte d’alerte lorsque le bouton de soumission est sélectionné.
void _showAlertDialog(BuildContext context, String title, String message) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: Text(message),
actions: [
TextButton(
child: const Text('OK'),
onPressed: () {
[Link](context).pop(); // Close the dialog
},
),
],
);
},
);
}
Maintenant, appelez cette méthode lorsque le bouton est cliqué.
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_logger.i('Form is valid. User input is logged.'); // Log the user
input
_showAlertDialog(context, 'Form Submitted', 'User input is logged.');
}
},
child: const Text('Submit'),
),
Étape 5 : Exécuter l'application
Personnalisez le design visuel de votre application Flutter en créant des
thèmes pour les couleurs, la typographie et les formes en utilisant
ThemeData.
Exemple : Créez un thème clair et un thème sombre pour l’application et
basculez entre eux en fonction des préférences de l’utilisateur.
M YOMBI Prince
MODULE 3 - TRAVAILLER AVEC FLUTTER
Explorez les capacités d’animation de Flutter pour ajouter des
animations interactives et des transitions entre les écrans, ou animer les
propriétés des widgets pour améliorer l’expérience utilisateur.
Apprenez à tester vos applications Flutter en utilisant le cadre de test
intégré pour les tests unitaires, les tests de widgets et les tests
d’intégration afin d’assurer la fiabilité de l’application.
M YOMBI Prince