Comment naviguer entre les pages de votre application Flutter
Sommaire
- 1- Introduction
- 1.1- Qu’est-ce que la navigation dans Flutter ?
- 1.2- Objectif du Cours
- 2- Navigation impérative avec
Navigator 1.0
- 2.1- Utilisation de
Navigator.push()
- 2.1.1- Explication de Code
- 2.2- Utilisation de
Navigator.pop()
- 2.3- Classes Associées à la Navigation Impérative
- 2.3.1-
MaterialPageRoute
- 2.3.2-
PageRouteBuilder
- 2.3.3- Conclusion
- 2.4- Activité
- 3- Navigation Déclarative avec
Navigator 2.0
- 3.1- RouterDelegate:
- 3.2- RouteInformationParser:
- 3.3- Utilisation de Navigator 2.0
- 3.4- Exemple d'Implémentation
- 4- Utilisation des
itinéraires nommés
- 4.1.1- Cours Flutter
Comment naviguer entre les pages de votre application Flutter
-
Introduction
-
Qu’est-ce que la navigation dans Flutter ?
- La navigation dans Flutter fait référence au passage d’un écran ou d’une page à un autre au sein de votre application. Il s’agit d’un aspect fondamental de la création d’applications mobiles, permettant aux utilisateurs d’explorer de manière transparente différentes sections ou fonctionnalités. Flutter fournit divers outils et techniques pour mettre en œuvre efficacement la navigation.
- Dans Flutter, les écrans et les pages sont appelés itinéraires, et ces itinéraires ne sont qu’un widget. Sous Android, un itinéraire est similaire à une activité, tandis que sous iOS, il équivaut à un ViewController.
- Dans n’importe quelle application mobile, la navigation vers différentes pages définit le flux de travail de l’application, et la manière de gérer la navigation est appelée routage.
- La navigation dans Flutter fait référence au passage d’un écran ou d’une page à une autre au sein de votre application. Elle permet aux utilisateurs d’explorer différentes sections ou fonctionnalités de manière fluide. Flutter offre deux types principaux de navigation :
- Navigation impérative : Basée sur Navigator 1.0, cette approche est traditionnelle et utilise des routes nommées ou anonymes.
- Navigation déclarative : Introduite avec Navigator 2.0, elle permet une gestion plus structurée des itinéraires via RouterDelegate et RouteInformationParser.
-
Objectif du Cours
- L’objectif principal est de comprendre et d’implémenter la navigation entre les pages dans une application Flutter, tout en explorant les différentes techniques et outils disponibles.
-
Navigation impérative avec
Navigator 1.0
-
Utilisation de
Navigator.push()
-
Utilisation4>
- Le moyen le plus courant de naviguer vers une nouvelle page dans Flutter consiste à utiliser la méthode Navigator.push.
- La méthode
Navigator.push()
est utilisée pour naviguer/passer à un nouvel itinéraire/page/écran. - Navigator.push prend deux arguments : le contexte et un objet Route.
- context est un BuildContext que Flutter utilise pour localiser le navigateur dans l’arborescence des widgets.
- Nous créons un MaterialPageRoute et spécifions la fonction builder, qui renvoie le widget à afficher sur la nouvelle page. Dans ce cas, il s’agit de SecondScreen.
-
Exemple4>
- Dans cet exemple, nous allons créer deux itinéraires de navigation.
- Dans les deux itinéraires, nous n’avons créé qu’un seul bouton.
- Lorsque nous appuyons sur le bouton de la première page, nous accédons à la deuxième page. Encore une fois, lorsque nous appuyons sur le bouton de la deuxième page, nous revenons à la première page.
-
Explication de Code
- Importation des packages :
import 'package:flutter/material.dart';
: Importation du package Flutter nécessaire pour construire l’interface utilisateur.- Fonction principale :
- Classe MyApp :
- MyApp est un widget sans état qui initialise l’application Flutter.
- MaterialApp configure le titre, le thème et la première page (FirstPage) de l’application.
- Classe FirstPage :
- FirstPage est un widget sans état qui représente la première page de l’application.
- Utilise Scaffold pour créer une structure de page avec une AppBar et un bouton centré.
- Le bouton utilise Navigator.push pour naviguer vers SecondPage lorsqu’il est pressé.
- Classe SecondPage :
- SecondPage est un widget sans état qui représente la deuxième page de l’application.
- Utilise Scaffold pour créer une structure de page avec une AppBar et un bouton centré.
- Le bouton utilise Navigator.pop pour revenir à FirstPage lorsqu’il est pressé.
-
Utilisation de
Navigator.pop()
-
Utilisation4>
- Lorsque vous êtes sur un nouvel écran et que vous souhaitez revenir au précédent, vous pouvez utiliser la méthode
Navigator.pop
. Navigator.pop
prend également un argument de contexte, supprime l’itinéraire actuel de la pile et revient à l’itinéraire précédent.-
Exemple4>
- Même exemple précédent
-
Fonctionnement de Navigator.pop4>
- Naviguer vers la deuxième page :
- Lorsqu’on appuie sur le bouton « Go to Second Page » dans FirstPage, Navigator.push est utilisé pour ajouter SecondPage en haut de la pile de navigation.
- Retour à la première page :
- Lorsqu’on appuie sur le bouton « Go back to First Page » dans SecondPage, Navigator.pop est utilisé pour supprimer SecondPage de la pile et revenir à FirstPage.
- Navigator.pop(context) prend le contexte comme argument, supprime la route actuelle de la pile de navigation et revient à la route précédente. Cela permet une navigation fluide et intuitive dans l’application Flutter.
-
Classes Associées à la Navigation Impérative
-
MaterialPageRoute
- Description:
- MaterialPageRoute est une classe qui implémente la navigation de type Material Design dans Flutter. Elle est utilisée pour créer des routes avec des animations par défaut lors de la transition entre les pages.
- Caractéristiques:
- Animation par défaut:
- Lorsqu’une nouvelle page est poussée sur la pile, MaterialPageRoute fournit une animation de glissement (slide) par défaut, où la nouvelle page glisse depuis la droite et la page précédente glisse vers la gauche.
- Utilisation simple:
- C’est le moyen le plus courant de naviguer entre les pages dans une application Flutter, car il nécessite peu de configuration.
- Exemple d’utilisation:
- Dans cet exemple, SecondScreen est la nouvelle page qui sera affichée lorsque l’utilisateur navigue.
-
PageRouteBuilder
- Description:
- PageRouteBuilder est une classe abstraite qui permet aux développeurs de créer des routes personnalisées avec des animations spécifiques. Cela offre plus de flexibilité par rapport à MaterialPageRoute.
- Caractéristiques:
- Personnalisation des animations: Avec PageRouteBuilder, vous pouvez définir vos propres animations pour l’entrée et la sortie des pages. Cela permet de créer des transitions uniques qui correspondent au style de votre application.
- Contrôle total: Vous avez un contrôle total sur le comportement de la transition, ce qui vous permet d’utiliser différents types d’animations (comme des fondus, des glissements, etc.).
- Exemple d’utilisation:
- Dans cet exemple :
- La nouvelle page (SecondScreen) glisse depuis la droite lorsque l’utilisateur navigue vers elle.
- Vous pouvez personnaliser le comportement de l’animation en modifiant les valeurs dans le Tween.
-
Conclusion
- Les classes MaterialPageRoute et PageRouteBuilder sont essentielles pour gérer la navigation dans les applications Flutter. Tandis que MaterialPageRoute offre une solution simple et efficace avec des animations par défaut, PageRouteBuilder permet une personnalisation avancée des transitions entre les pages. En fonction de vos besoins en matière d’interface utilisateur et d’expérience utilisateur, vous pouvez choisir l’une ou l’autre de ces classes pour gérer la navigation dans votre application. Si vous avez besoin d’autres informations ou d’exemples supplémentaires, n’hésitez pas à demander !
-
Activité
- Créer une classe de produit (facultatif)
- Si vous n’avez pas encore de classe pour représenter vos produits, vous pouvez en créer une. Voici un exemple simple :
- Nous allons créer deux pages : une page d’accueil (Page1) et une page secondaire (Page2).
- Page1
- Page2
- 4. Mettre à jour le fichier main.dart
- Maintenant, mettez à jour le fichier main.dart pour utiliser ces deux pages :
-
Navigation Déclarative avec
Navigator 2.0
- La navigation déclarative dans Flutter, introduite avec Navigator 2.0, offre une approche différente de la gestion de la navigation par rapport à la méthode impérative de Navigator 1.0. Voici un aperçu des concepts clés associés à cette nouvelle API.
Concepts Clés Navigator 2.0
est la référence standard en matière de navigation déclarative et ne remplace pas Navigator 1.0, car vous pouvez les utiliser ensemble.-
RouterDelegate:
- Description: Le RouterDelegate est responsable de la gestion des changements d’état dans votre application et de la reconstruction des écrans en conséquence. Il détermine quelles pages doivent être affichées en fonction de l’état actuel de l’application.
- Fonctionnement: Il utilise des méthodes pour construire l’interface utilisateur en fonction des informations de navigation, permettant une gestion plus fine et réactive des itinéraires.
-
RouteInformationParser:
- Description: Le RouteInformationParser interprète les informations de la route (généralement sous forme d’URL) pour décider quel écran afficher. Il convertit les chaînes d’URL ou d’autres informations en objets qui peuvent être utilisés par le
RouterDelegate
. - Fonctionnement: Cela permet aux applications d’être plus flexibles et de gérer des scénarios complexes, comme le deep linking (liens profonds) où une URL externe peut ouvrir directement une page spécifique de l’application.
-
Utilisation de Navigator 2.0
- Avec Navigator 2.0, vous pouvez gérer la navigation de manière plus déclarative, ce qui signifie que vous définissez l’état souhaité de votre interface utilisateur et laissez Flutter gérer les transitions et les changements d’état.
-
Exemple d’Implémentation
- Voici un exemple simple illustrant comment utiliser RouterDelegate et RouteInformationParser dans une application Flutter :
- Explication du Code
- MyApp : Utilise MaterialApp.router pour configurer la navigation avec un RouterDelegate et un RouteInformationParser.
- MyRouterDelegate : Gère l’état actuel de la navigation et construit l’interface utilisateur en fonction de l’état.
- MyRouteInformationParser : Interprète les informations de route pour déterminer quelle page doit être affichée.
- HomeScreen et SecondScreen : Deux pages simples qui permettent à l’utilisateur de naviguer entre elles.
- Conclusion
- La navigation déclarative avec Navigator 2.0 permet aux développeurs Flutter de gérer la navigation d’une manière plus flexible et réactive, facilitant le développement d’applications complexes avec des flux de navigation variés. En utilisant RouterDelegate et RouteInformationParser, vous pouvez créer des expériences utilisateur plus riches tout en maintenant une structure claire et maintenable dans votre code. Si vous avez besoin d’informations supplémentaires ou d’exemples spécifiques, n’hésitez pas à demander !
-
Utilisation des
itinéraires nommés
-
Utilisation5>
- Bien que les exemples ci-dessus fonctionnent bien pour les petites applications, il est courant d’utiliser des itinéraires nommés pour les applications plus volumineuses afin de conserver une structure de navigation claire et organisée.
- Les itinéraires nommés vous permettent de les spécifier et d’y accéder par leur nom sans créer un nouveau MaterialPageRoute à chaque fois.
- Dans ce code, nous définissons deux routes nommées : ‘/‘ pour le HomeScreen et ‘/second’ pour le SecondScreen. La propriété initialRoute spécifie le nom de l’itinéraire initial à afficher lors de la première ouverture de l’application.
- Navigator.pushNamed est utilisé pour parcourir l’itinéraire ‘/second’, correspondant au SecondScreen.
-
Exemple5>
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
}
Script de l’exemple
import 'package:flutter/material.dart';
// Point d'entrée principal de l'application
void main() {
runApp(MyApp());
}
// MyApp est le widget racine de l'application
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Titre de l'application
title: 'Flutter Navigation Demo',
// Définition du thème de l'application
theme: ThemeData(
primarySwatch: Colors.blue,
),
// Première page affichée lors du démarrage de l'application
home: FirstPage(),
);
}
}
// FirstPage est un widget sans état qui représente la première page
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
// AppBar en haut de la page avec un titre
appBar: AppBar(
title: Text('First Page'),
),
// Corps de la page contenant un bouton centré
body: Center(
child: ElevatedButton(
// Action exécutée lors de l'appui sur le bouton
onPressed: () {
// Navigation vers la deuxième page en utilisant Navigator.push
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
// Texte affiché sur le bouton
child: Text('Go to Second Page'),
),
),
);
}
}
// SecondPage est un widget sans état qui représente la deuxième page
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
// AppBar en haut de la page avec un titre
appBar: AppBar(
title: Text('Second Page'),
),
// Corps de la page contenant un bouton centré
body: Center(
child: ElevatedButton(
// Action exécutée lors de l'appui sur le bouton
onPressed: () {
// Retour à la première page en utilisant Navigator.pop
Navigator.pop(context);
},
// Texte affiché sur le bouton
child: Text('Go back to First Page'),
),
),
);
}
}
void main() { runApp(MyApp()); }
: Point d’entrée principal de l’application qui lance MyApp.onPressed: () {
Navigator.pop(context);
}
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => SecondScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(1.0, 0.0); // Commence à droite
const end = Offset.zero; // Fin à la position originale
const curve = Curves.easeInOut;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
var offsetAnimation = animation.drive(tween);
return SlideTransition(
position: offsetAnimation,
child: child,
);
},
),
);
Enoncé
class Product {
final String id;
final String name;
final String imageUrl;
final String description;
Product({
required this.id,
required this.name,
required this.imageUrl,
required this.description,
});
}
3. Créer les pages
import 'package:flutter/material.dart';
class Page1 extends StatelessWidget {
const Page1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Page 1')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(_createRoute());
},
child: const Text('Aller à la Page 2'),
),
),
);
}
Route _createRoute() {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => const Page2(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 1.0); // Commencer en bas
const end = Offset.zero; // Fin à la position originale
const curve = Curves.easeInOut; // Courbe d'animation
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
var offsetAnimation = animation.drive(tween);
return SlideTransition(
position: offsetAnimation,
child: child,
);
},
);
}
}
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('Page 2')),
body: Center(
child: Text('Bienvenue sur la Page 2!'),
),
);
}
}
import 'package:flutter/material.dart';
import 'page1.dart'; // Assurez-vous d'importer la bonne page
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigation avec Animation',
theme: ThemeData(primarySwatch: Colors.blue),
home: const Page1(),
);
}
}
Code de l’exemple
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: MyRouterDelegate(),
routeInformationParser: MyRouteInformationParser(),
);
}
}
class MyRouterDelegate extends RouterDelegate
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
String _selectedPage = 'home'; // Page par défaut
MyRouterDelegate() {
// Écoute les changements pour notifier les mises à jour
addListener(notifyListeners);
}
@override
String get currentConfiguration => _selectedPage;
@override
Widget build(BuildContext context) {
return Navigator(
pages: [
MaterialPage(child: HomeScreen(onTapped: _selectPage)),
if (_selectedPage == 'second') MaterialPage(child: SecondScreen()),
],
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
_selectedPage = 'home'; // Retour à la page d'accueil
notifyListeners();
return true;
},
);
}
void _selectPage(String page) {
_selectedPage = page;
notifyListeners();
}
}
class MyRouteInformationParser extends RouteInformationParser {
@override
Future parseRouteInformation(RouteInformation routeInformation) async {
final uri = Uri.parse(routeInformation.location!);
return uri.pathSegments.isNotEmpty ? uri.pathSegments.first : 'home';
}
@override
RouteInformation restoreRouteInformation(String configuration) {
return RouteInformation(location: '/$configuration');
}
}
class HomeScreen extends StatelessWidget {
final Function(String) onTapped;
HomeScreen({required this.onTapped});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () => onTapped('second'), // Naviguer vers SecondScreen
child: Text('Go to Second Page'),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Second Page')),
body: Center(
child: Text('Welcome to the Second Page!'),
),
);
}
}
void main() => runApp(
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/second': (context) => SecondScreen(),
},
),
);
Pour accéder à un itinéraire nommé, vous pouvez utiliser le code suivant :
onPressed: () {
Navigator.pushNamed(context, '/second');
}