导航到新屏幕并返回
如何实现页面之间的导航。
大多数应用程序包含多个用于展示不同类型信息的屏幕。例如,应用可能有一个显示产品的屏幕。当用户点击产品图片时,会跳转到一个显示产品详情的新屏幕。
在 Android 中,一个路由等同于一个 Activity。在 iOS 中,一个路由等同于一个 ViewController。而在 Flutter 中,一个路由仅仅是一个 Widget。
本指南使用 Navigator 来导航到新路由。
接下来的部分将通过以下步骤展示如何在两个路由之间导航:
- 创建两个路由。
- 使用
Navigator.push()导航到第二个路由。 - 使用
Navigator.pop()返回第一个路由。
1. 创建两个路由
#首先,创建两个用于演示的路由。由于这是一个基础示例,每个路由仅包含一个按钮。点击第一个路由上的按钮将导航到第二个路由。点击第二个路由上的按钮将返回到第一个路由。
首先,设置可视结构
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('First Route')),
body: Center(
child: ElevatedButton(
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 Scaffold(
appBar: AppBar(title: const Text('Second Route')),
body: Center(
child: ElevatedButton(
onPressed: () {
// Navigate back to first route when tapped.
},
child: const Text('Go back!'),
),
),
);
}
}
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!'),
),
),
);
}
}
2. 使用 Navigator.push() 导航至第二个路由
#要切换到新路由,请使用 Navigator.push() 方法。push() 方法会将一个 Route 添加到 Navigator 管理的路由堆栈中。Route 从何而来?你可以创建自己的路由,也可以使用平台特定的路由,例如 MaterialPageRoute 或 CupertinoPageRoute。平台特定的路由非常有用,因为它们会使用符合平台风格的动画过渡到新页面。
在 FirstRoute 组件的 build() 方法中,更新 onPressed() 回调:
// Within the `FirstRoute` widget:
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const SecondRoute(),
),
);
}
// Within the `FirstRoute` widget:
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute<void>(
builder: (context) => const SecondRoute(),
),
);
}
3. 使用 Navigator.pop() 返回第一个路由
#如何关闭第二个路由并返回到第一个路由?使用 Navigator.pop() 方法即可。pop() 方法会从 Navigator 管理的路由堆栈中移除当前的 Route。
要实现返回到原始路由的功能,请更新 SecondRoute 组件中的 onPressed() 回调:
// Within the SecondRoute widget
onPressed: () {
Navigator.pop(context);
}
互动示例
#import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(title: 'Navigation Basics', home: FirstRoute()));
}
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('First Route')),
body: Center(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const SecondRoute(),
),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Second Route')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
import 'package:flutter/cupertino.dart';
void main() {
runApp(const CupertinoApp(title: 'Navigation Basics', home: FirstRoute()));
}
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: () {
Navigator.push(
context,
CupertinoPageRoute<void>(
builder: (context) => const SecondRoute(),
),
);
},
),
),
);
}
}
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: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
其他导航方法
#本主题中的指南展示了使用 Navigator 类中的 push 和 pop 方法导航到新屏幕并返回上一级的基本方法,但 Navigator 还有其他几种静态方法可以使用。以下是其中一些:
-
pushAndRemoveUntil:将导航路由添加到堆栈,然后移除堆栈中最近的路由,直到满足特定条件。 -
pushReplacement:用新路由替换堆栈顶部的当前路由。 -
replace:将堆栈上的一个路由替换为另一个路由。 -
replaceRouteBelow:替换堆栈中特定路由下方的路由。 -
popUntil:移除导航路由堆栈中最近添加的路由,直到满足特定条件。 -
removeRoute:从堆栈中移除特定路由。 -
removeRouteBelow:移除堆栈中特定路由下方的路由。 -
restorablePush:恢复从堆栈中移除的路由。