diff --git a/examples/cookbook/navigation/navigation_basics/lib/main_step1_cupertino.dart b/examples/cookbook/navigation/navigation_basics/lib/main_step1_cupertino.dart new file mode 100644 index 0000000000..e4e79166c9 --- /dev/null +++ b/examples/cookbook/navigation/navigation_basics/lib/main_step1_cupertino.dart @@ -0,0 +1,42 @@ +import 'package:flutter/cupertino.dart'; + +// #docregion first-second-routes +class FirstRoute extends StatelessWidget { + const FirstRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('First Route')), + child: Center( + child: CupertinoButton( + child: const Text('Open route'), + onPressed: () { + // Navigate to second route when tapped. + }, + ), + ), + ); + } +} + +class SecondRoute extends StatelessWidget { + const SecondRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')), + child: Center( + child: CupertinoButton( + onPressed: () { + // Navigate back to first route when tapped. + }, + child: const Text('Go back!'), + ), + ), + ); + } +} + +// #enddocregion first-second-routes diff --git a/examples/cookbook/navigation/navigation_basics/lib/main_step2_cupertino.dart b/examples/cookbook/navigation/navigation_basics/lib/main_step2_cupertino.dart new file mode 100644 index 0000000000..2be3637822 --- /dev/null +++ b/examples/cookbook/navigation/navigation_basics/lib/main_step2_cupertino.dart @@ -0,0 +1,48 @@ +import 'package:flutter/cupertino.dart'; + +class FirstRoute extends StatelessWidget { + const FirstRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('First Route')), + child: Center( + child: CupertinoButton( + child: const Text('Open route'), + // #docregion first-route-on-pressed + // Within the `FirstRoute` widget: + onPressed: () { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => const SecondRoute()), + ); + }, + // #enddocregion first-route-on-pressed + ), + ), + ); + } +} + +class SecondRoute extends StatelessWidget { + const SecondRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')), + child: Center( + child: CupertinoButton( + // #docregion second-route-on-pressed + // Within the SecondRoute widget + onPressed: () { + Navigator.pop(context); + }, + // #enddocregion second-route-on-pressed + child: const Text('Go back!'), + ), + ), + ); + } +} diff --git a/src/content/cookbook/navigation/navigation-basics.md b/src/content/cookbook/navigation/navigation-basics.md index 15e3ecd168..364312d3e8 100644 --- a/src/content/cookbook/navigation/navigation-basics.md +++ b/src/content/cookbook/navigation/navigation-basics.md @@ -8,11 +8,11 @@ js: -Most apps contain several screens for displaying different types of -information. -For example, an app might have a screen that displays products. -When the user taps the image of a product, a new screen displays -details about the product. +Most apps contain several screens for displaying different +types of information. For example, an app might have a +screen that displays products. When the user taps the image +of a product, a new screen displays details about the +product. :::note Terminology In Flutter, _screens_ and _pages_ are called _routes_. @@ -29,8 +29,8 @@ The next few sections show how to navigate between two routes, using these steps: 1. Create two routes. - 2. Navigate to the second route using Navigator.push(). - 3. Return to the first route using Navigator.pop(). + 2. Navigate to the second route using `Navigator.push()`. + 3. Return to the first route using `Navigator.pop()`. ## 1. Create two routes @@ -41,6 +41,10 @@ second route returns to the first route. First, set up the visual structure: +{% tabs "os-android" %} + +{% tab "Android" %} + ```dart class FirstRoute extends StatelessWidget { @@ -82,18 +86,72 @@ class SecondRoute extends StatelessWidget { } ``` +{% endtab %} + +{% tab "iOS" %} + + +```dart +class FirstRoute extends StatelessWidget { + const FirstRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('First Route')), + child: Center( + child: CupertinoButton( + child: const Text('Open route'), + onPressed: () { + // Navigate to second route when tapped. + }, + ), + ), + ); + } +} + +class SecondRoute extends StatelessWidget { + const SecondRoute({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')), + child: Center( + child: CupertinoButton( + onPressed: () { + // Navigate back to first route when tapped. + }, + child: const Text('Go back!'), + ), + ), + ); + } +} +``` + +{% endtab %} + +{% endtabs %} + ## 2. Navigate to the second route using Navigator.push() To switch to a new route, use the [`Navigator.push()`][] method. The `push()` method adds a `Route` to the stack of routes managed by the `Navigator`. Where does the `Route` come from? -You can create your own, or use a [`MaterialPageRoute`][], -which is useful because it transitions to the -new route using a platform-specific animation. +You can create your own, or use a platform-specific route +such as [`MaterialPageRoute`][] or [`CupertinoPageRoute`][]. +A platform-specific route is useful because it transitions +to the new route using a platform-specific animation. In the `build()` method of the `FirstRoute` widget, update the `onPressed()` callback: +{% tabs "os-android" %} + +{% tab "Android" %} + ```dart // Within the `FirstRoute` widget: @@ -105,6 +163,25 @@ onPressed: () { } ``` +{% endtab %} + +{% tab "iOS" %} + + +```dart +// Within the `FirstRoute` widget: +onPressed: () { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => const SecondRoute()), + ); +} +``` + +{% endtab %} + +{% endtabs %} + ## 3. Return to the first route using Navigator.pop() How do you close the second route and return to the first? @@ -125,6 +202,10 @@ onPressed: () { ## Interactive example +{% tabs "os-android" %} + +{% tab "Android" %} + ```dartpad title="Flutter navigation hands-on example in DartPad" run="true" import 'package:flutter/material.dart'; @@ -179,32 +260,9 @@ class SecondRoute extends StatelessWidget { Navigation Basics Demo -## Navigation with CupertinoPageRoute +{% endtab %} -In the previous example you learned how to navigate between screens -using the [`MaterialPageRoute`][] from [Material Components][]. -However, in Flutter you are not limited to Material design language, -instead, you also have access to [Cupertino][] (iOS-style) widgets. - -Implementing navigation with Cupertino widgets follows the same steps -as when using [`MaterialPageRoute`][], -but instead you use [`CupertinoPageRoute`][] -which provides an iOS-style transition animation. - -In the following example, these widgets have been replaced: - -- [`MaterialApp`][] replaced by [`CupertinoApp`]. -- [`Scaffold`][] replaced by [`CupertinoPageScaffold`][]. -- [`ElevatedButton`][] replaced by [`CupertinoButton`][]. - -This way, the example follows the current iOS design language. - -:::secondary -You don't need to replace all Material widgets with Cupertino versions -to use [`CupertinoPageRoute`][] -since Flutter allows you to mix and match Material and Cupertino widgets -depending on your needs. -::: +{% tab "iOS" %} ```dartpad title="Flutter Cupertino theme hands-on example in DartPad" run="true" @@ -260,6 +318,10 @@ class SecondRoute extends StatelessWidget { Navigation Basics Cupertino Demo +{% endtab %} + +{% endtabs %} + ## Additional navigation methods The recipe in this topic shows you one way to navigate to a new screen and