Comment naviguer entre les pages de son application Flutter?


Avatar de Pierre Courtois

Naviguer entre les différentes pages de votre application est une fonctionnalité essentielle. Flutter propose plusieurs méthodes pour gérer la navigation, donc je vais vous présenter les plus courantes, accompagnées de leurs avantages, inconvénients et exemples simples.


Navigation pages flutter

Méthode 1 : Utiliser Navigator.push avec MaterialPageRoute

Cette méthode fonctionne comme suit :

Les différents widgets qui composent les pages de votre application, fonctionnent comme une pile de feuilles. Quand vous utilisez Navigator.push, Flutter empile une nouvelle page sur cette pile, qui agit comme un historique de la navigation de votre utilisateur.

La transition d’une page vers une autre va être gérée par MaterialPageRoute, qui fournit une transition animée par défaut basée sur les principes de Material Design.

Enfin, puisque votre application à en mémoire la dernière page consultée, vous pouvez revenir en arrière très simplement avec la méthode. Navigator.pop.

Si on la compare aux autres méthodes, ce qui fait la particularité de la méthode Navigator.push est que vos pages sont construites à la demande, au moment où vous les utilisez. Flutter va donc ignorer l’existence de tout ce qui n’est pas utilisé pendant l’usage de votre application.

En voici un exemple très simple :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PageUn(),
    );
  }
}

class PageUn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page 1')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => PageDeux()),
            );
          },
          child: Text('Aller à la Page 2'),
        ),
      ),
    );
  }
}

class PageDeux extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page 2')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context); // Revenir à la Page 1
          },
          child: Text('Revenir à la Page 1'),
        ),
      ),
    );
  }
}

Voici ce qui se passe :

  1. Transition animée : Flutter effectue une animation de transition (par défaut, glissement vers la gauche).
  2. Mise en mémoire : La page précédente reste en mémoire dans la pile.
  3. Gestion des états : Si la page précédente utilise des StatefulWidget, son état est conservé jusqu’à ce qu’elle soit retirée.

Quand utiliser cette méthode ?

Navigator.push est adapté si vous avez seulement quelques pages. Chaque fois que vous voulez aller quelque part, vous dites à Flutter exactement ce qu’il doit faire. Cette méthode vous permet aussi d’être plus créatif dans les transitions de pages que vous faites.

Dois-je créer plusieurs MaterialApp pour naviguer entre mes pages ?

Non, faites en sorte de n’avoir qu’un seul widget MaterialApp au début de votre code, après la fonction main. En effet, ce widget sert à définir le contexte global de l’application, ainsi qu’à gérer la navigation, le thème, et les transitions entre écrans.

Placer plusieurs MaterialApp dans des widgets comme des pages ou des routes (par exemple, dans un MaterialPageRoute) crée des contextes de navigation indépendants, ce qui peut entraîner des problèmes comme des reconstructions inattendues, des navigations incohérentes, ou des performances dégradées.

Au lieu de placer les pages de votre application dans une materialApp, placez les donc plutôt dans un Scaffold, qui fournit une structure standard avec des éléments comme une AppBar ou un body, tout en s’appuyant sur le MaterialApp racine pour le thème et la navigation.

Méthode 2 : Navigator.pushReplacement

La méthode Navigator.pushReplacement vous permet de remplacer une page par une autre sans que l’utilisateur puisse revenir à la page précédente. Elle est donc utile après des événements comme une connexion réussie où vous ne voulez pas que l’utilisateur puisse revenir directement à l’étape précédente.

Lorsque vous utilisez Navigator.pushReplacement, la page courante est ainsi supprimée de la pile de navigation et est remplacée par la nouvelle page.

Voici un code d’exemple :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: LoginPage(),
    );
  }
}

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page de Connexion')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Remplacer la page de connexion par la page d'accueil
            Navigator.pushReplacement(
              context,
              MaterialPageRoute(builder: (context) => HomePage()),
            );
          },
          child: Text('Se connecter'),
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page d\'accueil')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Remplacer la page d'accueil par la page de connexion
            Navigator.pushReplacement(
              context,
              MaterialPageRoute(builder: (context) => LoginPage()),
            );
          },
          child: Text('Se déconnecter'),
        ),
      ),
    );
  }
}

Quand utiliser cette méthode ?

Navigator.pushReplacement est adapté pour toutes les transitions de pages, où l’utilisateur n’est pas censé pouvoir revenir en arrière par la suite.

Méthode 3 : Utiliser Navigator.pushNamed

Avec Navigator.pushNamed, vous définissez des noms de routes dans le MaterialApp pour chaque page. Cette approche permet de centraliser la gestion des pages et de simplifier la navigation dans des applications avec de nombreuses pages. Pour faire une analogie, on peut comparer cette méthode à la navigation sur un site web utilisant des URLs.

Comme pour Navigator.push il existe une méthode Navigator.pushReplacementNamed, qui permet à l’utilisateur de se rendre sur une nouvelle page, sans possibilité de revenir sur la page d’origine.

Voici un code d’exemple :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/', // Page de démarrage
      routes: {
        '/': (context) => PageUn(),
        '/pageDeux': (context) => PageDeux(),
        '/pageTrois': (context) => PageTrois(),
      },
    );
  }
}

class PageUn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page 1')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/pageDeux');
          },
          child: Text('Aller à la Page 2'),
        ),
      ),
    );
  }
}

class PageDeux extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page 2')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/pageTrois');
          },
          child: Text('Aller à la Page 3'),
        ),
      ),
    );
  }
}

class PageTrois extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page 3')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context); // Retour à la Page 2
          },
          child: Text('Revenir à la Page 2'),
        ),
      ),
    );
  }
}

Si on la compare à la méthode Navigator.push, Navigator.pushNamed va créer un annuaire de vos pages au démarrage, pour plus facilement y accéder par la suite.

Sur un plan technique, voici ce qui se passe :

  1. Les routes sont définies dans le constructeur MaterialApp.
  2. Navigator.pushNamed utilise le nom d’une route ('/pageDeux') pour naviguer.

Quand utiliser cette méthode ?

Navigator.pushNamed est pratique si vous avez plein de pages à lier les unes autres et que vous voulez une méthode organisée pour naviguer sans avoir à répéter plusieurs fois le même bloc de code.

Conclusion

Vous êtes désormais capable de construire le squelette de votre application Flutter, utiliser des widgets de base, transmettre des informations d’un widget à un autre et passer d’une page de votre application à une autre.

Pourquoi ne pas continuez votre apprentissage en rendant votre application plus vivante grâce à la solution de back-end Firebase ?

Avatar de Pierre Courtois