| // 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. |
| |
| /// Flutter code sample for [Navigator]. |
| |
| import 'package:flutter/material.dart'; |
| |
| void main() => runApp(const MyApp()); |
| |
| class MyApp extends StatelessWidget { |
| const MyApp({super.key}); |
| |
| @override |
| Widget build(BuildContext context) { |
| return MaterialApp( |
| title: 'Flutter Code Sample for Navigator', |
| // MaterialApp contains our top-level Navigator |
| initialRoute: '/', |
| routes: <String, WidgetBuilder>{ |
| '/': (BuildContext context) => const HomePage(), |
| '/signup': (BuildContext context) => const SignUpPage(), |
| }, |
| ); |
| } |
| } |
| |
| class HomePage extends StatelessWidget { |
| const HomePage({super.key}); |
| |
| @override |
| Widget build(BuildContext context) { |
| return DefaultTextStyle( |
| style: Theme.of(context).textTheme.headlineMedium!, |
| child: Container( |
| color: Colors.white, |
| alignment: Alignment.center, |
| child: const Text('Home Page'), |
| ), |
| ); |
| } |
| } |
| |
| class CollectPersonalInfoPage extends StatelessWidget { |
| const CollectPersonalInfoPage({super.key}); |
| |
| @override |
| Widget build(BuildContext context) { |
| return DefaultTextStyle( |
| style: Theme.of(context).textTheme.headlineMedium!, |
| 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({ |
| super.key, |
| required this.onSignupComplete, |
| }); |
| |
| final VoidCallback onSignupComplete; |
| |
| @override |
| Widget build(BuildContext context) { |
| return GestureDetector( |
| onTap: onSignupComplete, |
| child: DefaultTextStyle( |
| style: Theme.of(context).textTheme.headlineMedium!, |
| child: Container( |
| color: Colors.pinkAccent, |
| alignment: Alignment.center, |
| child: const Text('Choose Credentials Page'), |
| ), |
| ), |
| ); |
| } |
| } |
| |
| class SignUpPage extends StatelessWidget { |
| const SignUpPage({super.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<void>(builder: builder, settings: settings); |
| }, |
| ); |
| } |
| } |