// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Template: dev/snippets/config/templates/freeform.tmpl // // Comment lines marked with "▼▼▼" and "▲▲▲" are used for authoring // of samples, and may be ignored if you are just exploring the sample. // Flutter code sample for Navigator // //*************************************************************************** //* ▼▼▼▼▼▼▼▼ description ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) // The following example demonstrates how a nested [Navigator] can be used to // present a standalone user registration journey. // // Even though this example uses two [Navigator]s to demonstrate nested // [Navigator]s, a similar result is possible using only a single [Navigator]. // // Run this example with `flutter run --route=/signup` to start it with // the signup flow instead of on the home page. //* ▲▲▲▲▲▲▲▲ description ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) //*************************************************************************** //**************************************************************************** //* ▼▼▼▼▼▼▼▼ code-imports ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) import 'package:flutter/material.dart'; //* ▲▲▲▲▲▲▲▲ code-imports ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) //**************************************************************************** //************************************************************************* //* ▼▼▼▼▼▼▼▼ code-main ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) void main() => runApp(const MyApp()); //* ▲▲▲▲▲▲▲▲ code-main ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) //************************************************************************* //******************************************************************** //* ▼▼▼▼▼▼▼▼ code ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Code Sample for Navigator', // MaterialApp contains our top-level Navigator initialRoute: '/', routes: { '/': (BuildContext context) => const HomePage(), '/signup': (BuildContext context) => const SignUpPage(), }, ); } } class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return DefaultTextStyle( style: Theme.of(context).textTheme.headline4!, child: Container( color: Colors.white, alignment: Alignment.center, child: const Text('Home Page'), ), ); } } class CollectPersonalInfoPage extends StatelessWidget { const CollectPersonalInfoPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return DefaultTextStyle( style: Theme.of(context).textTheme.headline4!, child: GestureDetector( onTap: () { // This moves from the personal info page to the credentials page, // replacing this page with that one. Navigator.of(context) .pushReplacementNamed('signup/choose_credentials'); }, child: Container( color: Colors.lightBlue, alignment: Alignment.center, child: const Text('Collect Personal Info Page'), ), ), ); } } class ChooseCredentialsPage extends StatelessWidget { const ChooseCredentialsPage({ Key? key, required this.onSignupComplete, }) : super(key: key); final VoidCallback onSignupComplete; @override Widget build(BuildContext context) { return GestureDetector( onTap: onSignupComplete, child: DefaultTextStyle( style: Theme.of(context).textTheme.headline4!, child: Container( color: Colors.pinkAccent, alignment: Alignment.center, child: const Text('Choose Credentials Page'), ), ), ); } } class SignUpPage extends StatelessWidget { const SignUpPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // SignUpPage builds its own Navigator which ends up being a nested // Navigator in our app. return Navigator( initialRoute: 'signup/personal_info', onGenerateRoute: (RouteSettings settings) { WidgetBuilder builder; switch (settings.name) { case 'signup/personal_info': // Assume CollectPersonalInfoPage collects personal info and then // navigates to 'signup/choose_credentials'. builder = (BuildContext context) => const CollectPersonalInfoPage(); break; case 'signup/choose_credentials': // Assume ChooseCredentialsPage collects new credentials and then // invokes 'onSignupComplete()'. builder = (BuildContext _) => ChooseCredentialsPage( onSignupComplete: () { // Referencing Navigator.of(context) from here refers to the // top level Navigator because SignUpPage is above the // nested Navigator that it created. Therefore, this pop() // will pop the entire "sign up" journey and return to the // "/" route, AKA HomePage. Navigator.of(context).pop(); }, ); break; default: throw Exception('Invalid route: ${settings.name}'); } return MaterialPageRoute(builder: builder, settings: settings); }, ); } } //* ▲▲▲▲▲▲▲▲ code ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) //********************************************************************