Objectif
- L'objectif de cette séance est de vous fournir une compréhension approfondie de la gestion de l'historique de navigation dans Flutter. À la fin de ce tutoriel, vous serez capable de :
- Créer une application Flutter avec une navigation de base entre plusieurs pages.
- Gérer l'historique de navigation pour permettre des transitions fluides entre les pages.
- Implémenter une navigation conditionnelle basée sur l'état de connexion de l'utilisateur.
-
Introduction à la navigation dans Flutter
- La navigation et le routage sont des aspects fondamentaux du développement d'applications. Ils permettent aux utilisateurs de se déplacer entre différents écrans et d'effectuer différentes actions. Dans Flutter, la gestion de l'historique de navigation se fait via une pile d'itinéraires, où chaque itinéraire représente un nouvel écran ou une nouvelle page. Flutter utilise le package Dart « dart:ui » pour gérer cette pile de routes.
- La navigation dans Flutter se fait principalement à l'aide de la classe
Navigator. Cette classe permet de gérer une pile de routes (ou pages) et offre diverses méthodes pour ajouter ou retirer des routes de la pile.Définitions
Route: Une route est une page ou un écran de votre application.Navigator: Un widget qui gère une pile de routes.
Activités
- Naviguer vers une nouvelle page: Ajouter une nouvelle route à la pile.
- Revenir à la page précédente: Retirer la route actuelle de la pile.
Comprendre l'historique de navigation
- L'historique de navigation est une pile de routes que l'utilisateur a visitées. Chaque fois qu'une nouvelle page est affichée, elle est poussée sur la pile. Lorsqu'on revient à la page précédente, la route actuelle est retirée de la pile.
Exemple
- Imaginons une application avec trois pages : A, B, et C. Si l'utilisateur navigue de A vers B, puis de B vers C, la pile ressemblera à ceci :[A, B, C]
- Si l'utilisateur revient à la page B, la pile devient :[A, B]
Naviguer vers un nouvel itinéraire
- Pour naviguer vers un nouvel itinéraire, vous pouvez utiliser la méthode Navigator.push. Cette méthode ajoute la route spécifiée en haut de la pile de routes. Flutter anime automatiquement la transition vers le nouvel itinéraire pour vous. Voici un exemple de la façon dont vous pouvez utiliser Navigator.push :
Navigator.push( contexte, MaterialPageRoute(builder : (contexte) => SecondRoute()), );Cela amènera Flutter à créer le widget SecondRoute et à l'animer sur l'écran, en superposant l'itinéraire actuel.
- Pour naviguer vers un nouvel itinéraire, vous pouvez utiliser la méthode Navigator.push. Cette méthode ajoute la route spécifiée en haut de la pile de routes. Flutter anime automatiquement la transition vers le nouvel itinéraire pour vous. Voici un exemple de la façon dont vous pouvez utiliser Navigator.push :
Revenir à l'itinéraire précédent
- Lorsque vous souhaitez revenir à l'itinéraire précédent, vous pouvez utiliser la méthode
Navigator.pop. - Cette méthode supprime la route supérieure de la pile et revient à la route précédente. Voici un exemple de la façon dont vous pouvez utiliser
Navigator.pop:Navigateur.pop (contexte);Cela permettra à Flutter de retirer l'itinéraire actuel de la pile et de revenir à l'itinéraire précédent, animant ainsi la transition pour vous.
- Lorsque vous souhaitez revenir à l'itinéraire précédent, vous pouvez utiliser la méthode
Naviguer vers un itinéraire nommé
- Pour naviguer vers un itinéraire nommé, vous pouvez utiliser la méthode
Navigator.pushNamed. - Cette méthode place la route portant le nom spécifié en haut de la pile. Voici un exemple de la façon dont vous pouvez utiliser Navigator.pushNamed :
Navigator.pushNamed(contexte, '/seconde');
- Pour naviguer vers un itinéraire nommé, vous pouvez utiliser la méthode
- L'historique de navigation est une pile de routes que l'utilisateur a visitées. Chaque fois qu'une nouvelle page est affichée, elle est poussée sur la pile. Lorsqu'on revient à la page précédente, la route actuelle est retirée de la pile.
Naviguer entre les pages
- Flutter offre plusieurs méthodes pour naviguer entre les pages :
Navigator.push: Pousse une nouvelle route sur la pile.Navigator.pop: Retire la route actuelle de la pile.Navigator.pushNamed: Pousse une route nommée sur la pile.Navigator.pushReplacement: Remplace la route actuelle par une nouvelle route.Exemple
- Pour revenir à la page précédente :
Navigator.pop(context);
Navigator.push( context, MaterialPageRoute(builder: (context) => NewPage()), );- Pour revenir à la page précédente :
Gérer l'historique de navigation
- La gestion de l'historique de navigation implique de manipuler la pile de routes pour offrir une expérience utilisateur optimale.
- Supprimer toutes les routes jusqu'à une route spécifique
Navigator.pushNamedAndRemoveUntil( context, '/newRoute', ModalRoute.withName('/home'), ); - Remplacer la route actuelle
Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => NewPage()), );
- Flutter offre plusieurs méthodes pour naviguer entre les pages :
Exemples pratiques
Exemple 1 : Navigation de base
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( initialRoute: '/', routes: { '/': (context) => HomePage(), '/second': (context) => SecondPage(), '/third': (context) => ThirdPage(), }, ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Home Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, '/second'); }, child: Text('Go to Second Page'), ), ), ); } } class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Second Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushNamed(context, '/third'); }, child: Text('Go to Third Page'), ), ), ); } } class ThirdPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Third Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.popUntil(context, ModalRoute.withName('/')); }, child: Text('Go to Home Page'), ), ), ); } }Exemple 2 : Remplacement de la route actuelle
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( initialRoute: '/', routes: { '/': (context) => HomePage(), '/second': (context) => SecondPage(), '/third': (context) => ThirdPage(), }, ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Home Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushReplacementNamed(context, '/second'); }, child: Text('Replace with Second Page'), ), ), ); } } class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Second Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushReplacementNamed(context, '/third'); }, child: Text('Replace with Third Page'), ), ), ); } } class ThirdPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Third Page')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pushReplacementNamed(context, '/'); }, child: Text('Replace with Home Page'), ), ), ); } }
Applications
-
Exercice 1 : Navigation de base
- Créez une application avec cinq pages : Accueil, Produits , Magasin, Vendeurs et Vente.
- Ajoutez des boutons pour naviguer entre les pages.
- Ajouter un menu pour chaque qui vous permet de naviguer entre les pages
-
Exercice 2 : Gestion de l'historique de navigation
- Modifiez l'application précédente pour utiliser Navigator.pushReplacement et
Navigator.pushNamedAndRemoveUntil. - Assurez-vous que l'utilisateur peut revenir à la page d'accueil depuis n'importe quelle page sans recharger la page.
- Modifiez l'application précédente pour utiliser Navigator.pushReplacement et
Exercice 3 : Navigation conditionnelle
- Ajoutez une condition pour vérifier si l'utilisateur est connecté avant de naviguer vers la Vente.
- Si l'utilisateur n'est pas connecté, affichez un message d'erreur et restez sur la page actuelle.
-
Solution
-
Exercice 1 : Navigation de base
- Objectif
- Créez une application avec cinq pages : Accueil, Produits, Magasin, Vendeurs, et Vente. Ajoutez des boutons pour naviguer entre les pages et un menu pour chaque page qui permet de naviguer entre les pages.
- Étapes
- Créez un projet Flutter.
- Ajoutez cinq pages : HomePage, ProductsPage, StorePage, SellersPage, et SalesPage.
- Ajoutez des boutons et un menu pour naviguer entre les pages.
Étape 1 : Créez un projet Flutter
flutter create navigation_example cd navigation_exampleÉtape 2 : Créez les cinq pages
- main.dart
import 'package:flutter/material.dart'; import 'home_page.dart'; import 'products_page.dart'; import 'store_page.dart'; import 'sellers_page.dart'; import 'sales_page.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Navigation Example', theme: ThemeData( primarySwatch: Colors.blue, ), initialRoute: '/', routes: { '/': (context) => HomePage(), '/products': (context) => ProductsPage(), '/store': (context) => StorePage(), '/sellers': (context) => SellersPage(), '/sales': (context) => SalesPage(), }, ); } } - home_page.dart
- Créez des pages similaires pour products_page.dart, store_page.dart, sellers_page.dart, et sales_page.dart.
import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Accueil'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page d\'accueil!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - products_page.dart
import 'package:flutter/material.dart'; class ProductsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Produits'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page des produits!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - Répétez ce processus pour les autres pages (store_page.dart, sellers_page.dart, sales_page.dart).
- store_page.dart
import 'package:flutter/material.dart'; class StorePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Magasin'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page du magasin!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - sellers_page.dart
import 'package:flutter/material.dart'; class SellersPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Vendeurs'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page des vendeurs!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - sales_page.dart
import 'package:flutter/material.dart'; class SalesPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Vente'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page des ventes!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), ]; }, ); } } - Explications
- Chaque fichier Dart définit une page avec une AppBar, un PopupMenuButton pour naviguer entre les différentes pages, et un Center widget pour afficher le contenu de la page.
- Le PopupMenuButton contient des PopupMenuItem pour chaque page de votre application.
- La fonction onSelected de chaque PopupMenuButton utilise Navigator.pushNamed pour naviguer vers la page sélectionnée.
- main.dart
-
Exercice 2 : Gestion de l’historique de navigation
- Objectif
- Modifiez l’application précédente pour utiliser Navigator.pushReplacement et
Navigator.pushNamedAndRemoveUntil. Assurez-vous que l’utilisateur peut revenir à la page d’accueil depuis n’importe quelle page sans recharger la page.
- Modifiez l’application précédente pour utiliser Navigator.pushReplacement et
- Étapes
- Modifiez les fonctions de navigation pour utiliser Navigator.pushReplacement et Navigator.pushNamedAndRemoveUntil.
- main.dart (pas de modification nécessaire pour ce fichier)
- home_page.dart
import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Accueil'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page d\'accueil!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { Navigator.pushReplacementNamed(context, value); }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - Modifiez également les autres pages pour utiliser Navigator.pushReplacementNamed.
- products_page.dart
import 'package:flutter/material.dart'; class ProductsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Produits'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page des produits!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { if (value == '/') { Navigator.pushNamedAndRemoveUntil(context, value, (Route route) => false); } else { Navigator.pushReplacementNamed(context, value); } }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - Répétez ce processus pour les autres pages (store_page.dart, sellers_page.dart, sales_page.dart).
-
Exercice 3 : Navigation conditionnelle
- Objectif
- Ajoutez une condition pour vérifier si l’utilisateur est connecté avant de naviguer vers la page des vendeurs. Si l’utilisateur n’est pas connecté, affichez un message d’erreur et restez sur la page actuelle.
- Étapes
- Simulez l’état de connexion de l’utilisateur.
- Ajoutez une condition pour vérifier si l’utilisateur est connecté avant de naviguer vers la page des vendeurs.
- main.dart (pas de modification nécessaire pour ce fichier)
- home_page.dart
import 'package:flutter/material.dart'; class HomePage extends StatelessWidget { final bool isLoggedIn = false; // Simule l'état de connexion de l'utilisateur @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Accueil'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page d\'accueil!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { if (value == '/sellers' && !isLoggedIn) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Vous devez être connecté pour accéder à cette page.')), ); } else { Navigator.pushReplacementNamed(context, value); } }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/products', child: Text('Produits'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } - Répétez cette vérification pour les autres pages où vous souhaitez ajouter cette condition de connexion. Par exemple, dans products_page.dart :
import 'package:flutter/material.dart'; class ProductsPage extends StatelessWidget { final bool isLoggedIn = false; // Simule l'état de connexion de l'utilisateur @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Produits'), actions: [buildMenu(context)], ), body: Center( child: Text('Bienvenue à la page des produits!'), ), ); } Widget buildMenu(BuildContext context) { return PopupMenuButton( onSelected: (String value) { if (value == '/sellers' && !isLoggedIn) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Vous devez être connecté pour accéder à cette page.')), ); } else { Navigator.pushReplacementNamed(context, value); } }, itemBuilder: (BuildContext context) { return [ PopupMenuItem ( value: '/', child: Text('Accueil'), ), PopupMenuItem ( value: '/store', child: Text('Magasin'), ), PopupMenuItem ( value: '/sellers', child: Text('Vendeurs'), ), PopupMenuItem ( value: '/sales', child: Text('Vente'), ), ]; }, ); } } Conclusion
- En suivant ces exercices, vous devriez maintenant être capable de :
- Créer une application Flutter avec une navigation de base entre plusieurs pages.
- Gérer l'historique de navigation pour permettre des transitions fluides entre les pages.
- Implémenter une navigation conditionnelle basée sur l'état de connexion de l'utilisateur.
- Objectif
- Objectif
Voir la solution
-