Skip to content

Commit 32ec393

Browse files
authored
Navigate to a new screen and back (add stronger iOS support) (#11776)
_Description of what this PR is changing or adding, and why:_ * Merged the iOS topic at the bottom of the guide into the existing recipe so that a developer can quickly toggle between Android and iOS steps. * Added additional code snippet tests for the iOS samples. _Issues fixed by this PR (if any):_ _PRs or commits this PR depends on (if any):_ ## Presubmit checklist - [x] This PR is marked as draft with an explanation if not meant to land until a future stable release. - [x] This PR doesn’t contain automatically generated corrections (Grammarly or similar). - [x] This PR follows the [Google Developer Documentation Style Guidelines](https://developers.google.com/style) — for example, it doesn’t use _i.e._ or _e.g._, and it avoids _I_ and _we_ (first person). - [x] This PR uses [semantic line breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks) of 80 characters or fewer.
1 parent 5c3e68a commit 32ec393

File tree

3 files changed

+187
-35
lines changed

3 files changed

+187
-35
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:flutter/cupertino.dart';
2+
3+
// #docregion first-second-routes
4+
class FirstRoute extends StatelessWidget {
5+
const FirstRoute({super.key});
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
return CupertinoPageScaffold(
10+
navigationBar: const CupertinoNavigationBar(middle: Text('First Route')),
11+
child: Center(
12+
child: CupertinoButton(
13+
child: const Text('Open route'),
14+
onPressed: () {
15+
// Navigate to second route when tapped.
16+
},
17+
),
18+
),
19+
);
20+
}
21+
}
22+
23+
class SecondRoute extends StatelessWidget {
24+
const SecondRoute({super.key});
25+
26+
@override
27+
Widget build(BuildContext context) {
28+
return CupertinoPageScaffold(
29+
navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')),
30+
child: Center(
31+
child: CupertinoButton(
32+
onPressed: () {
33+
// Navigate back to first route when tapped.
34+
},
35+
child: const Text('Go back!'),
36+
),
37+
),
38+
);
39+
}
40+
}
41+
42+
// #enddocregion first-second-routes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import 'package:flutter/cupertino.dart';
2+
3+
class FirstRoute extends StatelessWidget {
4+
const FirstRoute({super.key});
5+
6+
@override
7+
Widget build(BuildContext context) {
8+
return CupertinoPageScaffold(
9+
navigationBar: const CupertinoNavigationBar(middle: Text('First Route')),
10+
child: Center(
11+
child: CupertinoButton(
12+
child: const Text('Open route'),
13+
// #docregion first-route-on-pressed
14+
// Within the `FirstRoute` widget:
15+
onPressed: () {
16+
Navigator.push(
17+
context,
18+
CupertinoPageRoute(builder: (context) => const SecondRoute()),
19+
);
20+
},
21+
// #enddocregion first-route-on-pressed
22+
),
23+
),
24+
);
25+
}
26+
}
27+
28+
class SecondRoute extends StatelessWidget {
29+
const SecondRoute({super.key});
30+
31+
@override
32+
Widget build(BuildContext context) {
33+
return CupertinoPageScaffold(
34+
navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')),
35+
child: Center(
36+
child: CupertinoButton(
37+
// #docregion second-route-on-pressed
38+
// Within the SecondRoute widget
39+
onPressed: () {
40+
Navigator.pop(context);
41+
},
42+
// #enddocregion second-route-on-pressed
43+
child: const Text('Go back!'),
44+
),
45+
),
46+
);
47+
}
48+
}

src/content/cookbook/navigation/navigation-basics.md

+97-35
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ js:
88

99
<?code-excerpt path-base="cookbook/navigation/navigation_basics"?>
1010

11-
Most apps contain several screens for displaying different types of
12-
information.
13-
For example, an app might have a screen that displays products.
14-
When the user taps the image of a product, a new screen displays
15-
details about the product.
11+
Most apps contain several screens for displaying different
12+
types of information. For example, an app might have a
13+
screen that displays products. When the user taps the image
14+
of a product, a new screen displays details about the
15+
product.
1616

1717
:::note Terminology
1818
In Flutter, _screens_ and _pages_ are called _routes_.
@@ -29,8 +29,8 @@ The next few sections show how to navigate between two routes,
2929
using these steps:
3030

3131
1. Create two routes.
32-
2. Navigate to the second route using Navigator.push().
33-
3. Return to the first route using Navigator.pop().
32+
2. Navigate to the second route using `Navigator.push()`.
33+
3. Return to the first route using `Navigator.pop()`.
3434

3535
## 1. Create two routes
3636

@@ -41,6 +41,10 @@ second route returns to the first route.
4141

4242
First, set up the visual structure:
4343

44+
{% tabs "os-android" %}
45+
46+
{% tab "Android" %}
47+
4448
<?code-excerpt "lib/main_step1.dart (first-second-routes)"?>
4549
```dart
4650
class FirstRoute extends StatelessWidget {
@@ -82,18 +86,72 @@ class SecondRoute extends StatelessWidget {
8286
}
8387
```
8488

89+
{% endtab %}
90+
91+
{% tab "iOS" %}
92+
93+
<?code-excerpt "lib/main_step1_cupertino.dart (first-second-routes)"?>
94+
```dart
95+
class FirstRoute extends StatelessWidget {
96+
const FirstRoute({super.key});
97+
98+
@override
99+
Widget build(BuildContext context) {
100+
return CupertinoPageScaffold(
101+
navigationBar: const CupertinoNavigationBar(middle: Text('First Route')),
102+
child: Center(
103+
child: CupertinoButton(
104+
child: const Text('Open route'),
105+
onPressed: () {
106+
// Navigate to second route when tapped.
107+
},
108+
),
109+
),
110+
);
111+
}
112+
}
113+
114+
class SecondRoute extends StatelessWidget {
115+
const SecondRoute({super.key});
116+
117+
@override
118+
Widget build(BuildContext context) {
119+
return CupertinoPageScaffold(
120+
navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')),
121+
child: Center(
122+
child: CupertinoButton(
123+
onPressed: () {
124+
// Navigate back to first route when tapped.
125+
},
126+
child: const Text('Go back!'),
127+
),
128+
),
129+
);
130+
}
131+
}
132+
```
133+
134+
{% endtab %}
135+
136+
{% endtabs %}
137+
85138
## 2. Navigate to the second route using Navigator.push()
86139

87140
To switch to a new route, use the [`Navigator.push()`][]
88141
method. The `push()` method adds a `Route` to the stack of routes managed by
89142
the `Navigator`. Where does the `Route` come from?
90-
You can create your own, or use a [`MaterialPageRoute`][],
91-
which is useful because it transitions to the
92-
new route using a platform-specific animation.
143+
You can create your own, or use a platform-specific route
144+
such as [`MaterialPageRoute`][] or [`CupertinoPageRoute`][].
145+
A platform-specific route is useful because it transitions
146+
to the new route using a platform-specific animation.
93147

94148
In the `build()` method of the `FirstRoute` widget,
95149
update the `onPressed()` callback:
96150

151+
{% tabs "os-android" %}
152+
153+
{% tab "Android" %}
154+
97155
<?code-excerpt "lib/main_step2.dart (first-route-on-pressed)" replace="/^\},$/}/g"?>
98156
```dart
99157
// Within the `FirstRoute` widget:
@@ -105,6 +163,25 @@ onPressed: () {
105163
}
106164
```
107165

166+
{% endtab %}
167+
168+
{% tab "iOS" %}
169+
170+
<?code-excerpt "lib/main_step2_cupertino.dart (first-route-on-pressed)" replace="/^\},$/}/g"?>
171+
```dart
172+
// Within the `FirstRoute` widget:
173+
onPressed: () {
174+
Navigator.push(
175+
context,
176+
CupertinoPageRoute(builder: (context) => const SecondRoute()),
177+
);
178+
}
179+
```
180+
181+
{% endtab %}
182+
183+
{% endtabs %}
184+
108185
## 3. Return to the first route using Navigator.pop()
109186

110187
How do you close the second route and return to the first?
@@ -125,6 +202,10 @@ onPressed: () {
125202

126203
## Interactive example
127204

205+
{% tabs "os-android" %}
206+
207+
{% tab "Android" %}
208+
128209
<?code-excerpt "lib/main.dart"?>
129210
```dartpad title="Flutter navigation hands-on example in DartPad" run="true"
130211
import 'package:flutter/material.dart';
@@ -179,32 +260,9 @@ class SecondRoute extends StatelessWidget {
179260
<img src="/assets/images/docs/cookbook/navigation-basics.gif" alt="Navigation Basics Demo" class="site-mobile-screenshot" />
180261
</noscript>
181262

182-
## Navigation with CupertinoPageRoute
263+
{% endtab %}
183264

184-
In the previous example you learned how to navigate between screens
185-
using the [`MaterialPageRoute`][] from [Material Components][].
186-
However, in Flutter you are not limited to Material design language,
187-
instead, you also have access to [Cupertino][] (iOS-style) widgets.
188-
189-
Implementing navigation with Cupertino widgets follows the same steps
190-
as when using [`MaterialPageRoute`][],
191-
but instead you use [`CupertinoPageRoute`][]
192-
which provides an iOS-style transition animation.
193-
194-
In the following example, these widgets have been replaced:
195-
196-
- [`MaterialApp`][] replaced by [`CupertinoApp`].
197-
- [`Scaffold`][] replaced by [`CupertinoPageScaffold`][].
198-
- [`ElevatedButton`][] replaced by [`CupertinoButton`][].
199-
200-
This way, the example follows the current iOS design language.
201-
202-
:::secondary
203-
You don't need to replace all Material widgets with Cupertino versions
204-
to use [`CupertinoPageRoute`][]
205-
since Flutter allows you to mix and match Material and Cupertino widgets
206-
depending on your needs.
207-
:::
265+
{% tab "iOS" %}
208266

209267
<?code-excerpt "lib/main_cupertino.dart"?>
210268
```dartpad title="Flutter Cupertino theme hands-on example in DartPad" run="true"
@@ -260,6 +318,10 @@ class SecondRoute extends StatelessWidget {
260318
<img src="/assets/images/docs/cookbook/navigation-basics-cupertino.gif" alt="Navigation Basics Cupertino Demo" class="site-mobile-screenshot" />
261319
</noscript>
262320

321+
{% endtab %}
322+
323+
{% endtabs %}
324+
263325
## Additional navigation methods
264326

265327
The recipe in this topic shows you one way to navigate to a new screen and

0 commit comments

Comments
 (0)