Gestion de l’historique de navigation dans Flutter
Sommaire
- 1- Objectif
- 2- Introduction à la navigation dans Flutter
- 2.1- Définitions
- 2.2- Activités
- 3- Comprendre l'historique de navigation
- 3.1- Exemple
- 3.2- Naviguer vers un nouvel itinéraire
- 3.3- Revenir à l'itinéraire précédent
- 3.4- Naviguer vers un itinéraire nommé
- 4- Naviguer entre les pages
- 4.1- Exemple
- 4.2- Gérer l'historique de navigation
- 5- Exemples pratiques
- 5.1- Exemple 1 : Navigation de base
- 5.2- Exemple 2 : Remplacement de la route actuelle
- 6- Applications
- 6.1- Exercice 1 : Navigation de base
- 6.2- Exercice 2 : Gestion de l'historique de navigation
- 6.3- Exercice 3 : Navigation conditionnelle
- 7- Solution
- 7.1- Exercice 1 : Navigation de base
- 7.1.1- Étape 1 : Créez un projet Flutter
- 7.1.2- Étape 2 : Créez les cinq pages
- 7.2- Exercice 2 : Gestion de l’historique de navigation
- 7.3- Exercice 3 : Navigation conditionnelle
- 7.4- Conclusion
- 7.4.1- Cours Flutter
Gestion de l’historique de navigation dans Flutter
-
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 :
-
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
: -
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 :
-
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);
-
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
- Remplacer la route actuelle
-
Exemples pratiques
-
Exemple 1 : Navigation de base
-
Exemple 2 : Remplacement de la route actuelle
-
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.
-
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
-
Étape 2 : Créez les cinq pages
- main.dart
- home_page.dart
- Créez des pages similaires pour products_page.dart, store_page.dart, sellers_page.dart, et sales_page.dart.
- products_page.dart
- Répétez ce processus pour les autres pages (store_page.dart, sellers_page.dart, sales_page.dart).
- store_page.dart
- sellers_page.dart
- sales_page.dart
- 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.
-
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. - É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
- Modifiez également les autres pages pour utiliser Navigator.pushReplacementNamed.
- products_page.dart
- 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
- Répétez cette vérification pour les autres pages où vous souhaitez ajouter cette condition de connexion. Par exemple, dans products_page.dart :
-
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.
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.
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.
Navigator.pushNamed(contexte, '/seconde');
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NewPage()),
);
Navigator.pushNamedAndRemoveUntil(
context,
'/newRoute',
ModalRoute.withName('/home'),
);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => NewPage()),
);
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'),
),
),
);
}
}
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'),
),
),
);
}
}
Voir la solution
flutter create navigation_example
cd navigation_example
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(),
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}
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'),
),
];
},
);
}
}