📝 Introduction : Pourquoi la Navigation est-elle Essentielle ?
Dans une application Flutter, l’utilisateur doit pouvoir naviguer naturellement entre plusieurs écrans. Une application moderne n’est pas statique : elle doit guider l’utilisateur d’un point A à un point B avec fluidité, que ce soit via des boutons, un menu latéral, ou une barre d’onglets en bas de l’écran.
Flutter offre plusieurs outils puissants pour gérer cette navigation :
✅ Le Navigator
pour passer d’un écran à un autre.
✅ Le BottomNavigationBar
pour une navigation rapide entre plusieurs sections.
✅ Le Drawer
pour un menu latéral déployable.
✅ Les routes nommées pour organiser une navigation structurée.
Dans cet article, nous allons explorer chacune de ces solutions, en expliquant quand et pourquoi les utiliser, avec des exemples concrets.
| source: https://www.mobiapps.fr/blog/flutter-la-navigation
1️⃣ Le Navigator
: La Base de la Navigation
Flutter utilise un système de pile (stack) pour gérer les écrans. Chaque nouvel écran est empilé au-dessus des précédents, et lorsqu’un utilisateur appuie sur "Retour", l’écran est dépilé.
👉 Cas d’usage : Lorsque vous avez un bouton permettant de passer d’un écran à un autre.
** Exemple : Passer à une nouvelle page avec Navigator.push()
**
Créons deux fichiers :
-
main.dart
(page principale). -
page2.dart
(seconde page).
main.dart
:
import 'package:flutter/material.dart';
import 'page2.dart'; // Importation de la deuxième page
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const Page1(),
);
}
}
class Page1 extends StatelessWidget {
const Page1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Article : Flutter')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Page2()),
);
},
child: const Text('Prendre le bus vers Rosemont'),
),
),
);
}
}
page2.dart
:
import 'package:flutter/material.dart';
class Page2 extends StatelessWidget {
const Page2({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Arrivé à Rosemont')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context); // Revenir à la page précédente
},
child: const Text('Retour à la maison'),
),
),
);
}
}
Explication :
-
Navigator.push()
ajoute un nouvel écran à la pile. -
Navigator.pop()
retire l’écran courant et revient en arrière.
Résultat :
2️⃣ Le BottomNavigationBar
: Une Barre de Navigation Moderne
Un BottomNavigationBar
est souvent utilisé pour permettre un accès rapide aux sections principales d’une application. C’est l’un des modèles de navigation les plus courants.
👉 Cas d’usage : Application avec 3 à 5 pages principales.
Exemple : Ajouter un BottomNavigationBar
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const PageNavigation(),
);
}
}
class PageNavigation extends StatefulWidget {
const PageNavigation({Key? key}) : super(key: key);
@override
_PageNavigationState createState() => _PageNavigationState();
}
class _PageNavigationState extends State<PageNavigation> {
int _selectedIndex = 0;
static const List<Widget> _pages = <Widget>[
Center(child: Text('🏠 Le Collège de Rosemont', style: TextStyle(fontSize: 24))),
Center(child: Text('👤 Je suis un étudiant', style: TextStyle(fontSize: 24))),
Center(child: Text('⚙️ Apprendre la programmation', style: TextStyle(fontSize: 24))),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Navigation avec BottomNavigationBar')),
body: _pages[_selectedIndex], // Affiche la page sélectionnée
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Rosemont'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Étudiant'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Programmation'),
],
),
);
}
}
Explication :
-
_selectedIndex
garde l’index actif. -
_pages
contient les trois écrans possibles. -
setState()
met à jour l’index lorsqu’un onglet est cliqué.
Résultat :
| source: https://codewithandrea.com/articles/multiple-navigators-bottom-navigation-bar/
3️⃣ Drawer
: Un Menu Latéral Déroulant
Un Drawer
est utilisé pour accéder aux paramètres avancés ou aux pages moins courantes.
👉 Cas d’usage : Lorsque vous avez beaucoup d’options de navigation.
Exemple : Ajouter un Drawer
avec plusieurs options :
Dans cet exemple, le Drawer
(menu latéral) est intégré directement dans la page principale pour simplifier la démonstration.
💡 Cependant, dans une vraie application Flutter bien structurée, il est préférable de créer le menu sous forme de widget séparé et de l’importer dans la page principale.
Dans nos précédents articles, nous avons déjà vu comment créer un widget dédié et l’importer. Pour rappel, voici les étapes générales :
1️⃣ Créer un fichier séparé mon_drawer.dart
et y définir le Drawer
.
2️⃣ L’importer dans main.dart
et l’utiliser dans le Scaffold
.
3️⃣ Maintenir un code propre et modulaire pour une meilleure organisation.
👉 Comme cet article est déjà long, nous avons réalisé l’exemple avec le menu directement dans la page.
👉 Pour une mise en œuvre plus professionnelle, merci de vous référer à nos précédents articles sur la création et l'importation des widgets.
Pourquoi utiliser un fichier séparé pour le Drawer
?
✅ Meilleure organisation : Séparer la logique de navigation du reste du code.
✅ Réutilisation facile : Le menu peut être utilisé dans plusieurs pages.
✅ Facilitation de maintenance : Modifier le menu sans toucher à la page principale.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: const PagePrincipale(),
);
}
}
class PagePrincipale extends StatefulWidget {
const PagePrincipale({Key? key}) : super(key: key);
@override
_PagePrincipaleState createState() => _PagePrincipaleState();
}
class _PagePrincipaleState extends State<PagePrincipale> {
int _selectedIndex = 0;
static const List<Widget> _pages = <Widget>[
Center(child: Text('🏠 Le Collège de Rosemont', style: TextStyle(fontSize: 24))),
Center(child: Text('👤 Je suis un étudiant', style: TextStyle(fontSize: 24))),
Center(child: Text('⚙️ Programmation', style: TextStyle(fontSize: 24))),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Application Flutter')),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Text('Menu de Navigation',
style: TextStyle(color: Colors.white, fontSize: 20)),
),
ListTile(
leading: const Icon(Icons.info),
title: const Text('Étudiant'),
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('À propos sélectionné')));
},
),
ListTile(
leading: const Icon(Icons.help),
title: const Text('Rosemont'),
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Support sélectionné')));
},
),
ListTile(
leading: const Icon(Icons.logout),
title: const Text('Déconnexion'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Rosemont'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Étudiant'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Programmation'),
],
),
);
}
}
Explication :
-
DrawerHeader
affiche le titre du menu. -
ListTile
représente chaque option du menu.
| source: https://docs.flutter.dev/cookbook/navigation/navigation-basics
Conclusion
Nous avons exploré les méthodes essentielles de navigation en Flutter. Chaque approche a son usage optimal selon la structure de l’application.
👉 Dans le prochain article, nous verrons les animations et transitions avancées en Flutter !
Références :
Site officiel de Flutter : https://flutter.dev/ (Page consultée le 14 mars 2025).
Documentation Flutter : https://docs.flutter.dev/ (Page consultée le 14 mars 2025).
FAQ Flutter : https://docs.flutter.dev/resources/faq (Page consultée le 14 mars2025).
Flutter (logiciel) – Wikipédia : https://fr.wikipedia.org/wiki/Flutter_(logiciel) (Page consultée le 14 mars 2025).
Flutter sur GitHub (open source) : https://github.com/flutter/flutter (Page consultée le 14 mars 2025).
Code with Andrea (Tutoriel) : https://codewithandrea.com/articles/multiple-navigators-bottom-navigation-bar/ (Page consultée le 14 mars 2025).
Site officiel de Flutter : https://docs.flutter.dev/cookbook/navigation/navigation-basics (Page consultée le 14 mars 2025).
Lien pour la première image et aussi pour un tuto sur la navigation : https://www.kindacode.com/article/flutter-best-packages-to-create-bottom-app-bar (Page consultée le 14 mars 2025).
À très bientôt !
Commentaires1
C'est très intéressant de…
C'est très intéressant de voir l'animation de Flutter en temps réel, tu nous présente de très bons exemples concrets ! Je me demandais quel widget de navigation t'as paru le plus adapté pour tes exemples ? (Drawer, BottomNavigationBar, ou Navigator)