用 Navigator.push 和 pop 压入、弹出界面,通过构造函数传递数据,并在界面关闭时取回一个结果。
在 Kodokon 中打开本课Flutter 把你的界面当作一个栈来管理:Navigator.push 把新界面放到顶部,Navigator.pop 移除顶部的界面并显露出前一个。每个界面都是一条路由,而 MaterialPageRoute 会提供该平台原生的过渡动画。Android 的返回键会替你调用 pop,你一行代码都不用写。
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: FilledButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const DetailScreen(
productName: 'Headphones',
);
},
),
);
},
child: const Text('View product'),
),
),
);
}
}要把数据传给下一个界面,并没有什么魔法机制:目标界面就是一个和其他 widget 一样的 widget,它通过构造函数接收自己的数据。这是有类型、明确的,而且如果漏了某个字段,编译器会当场抓住你。注意,被压入的界面的 AppBar 会自动显示返回键,你什么都不用写。
import 'package:flutter/material.dart';
class DetailScreen extends StatelessWidget {
const DetailScreen({
super.key,
required this.productName,
});
final String productName;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(productName)),
body: Center(
child: FilledButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Add to cart'),
),
),
);
}
}Navigator.push 会返回一个 Future,它在界面关闭时以传给 pop 的值完成。因此你可以等待一个界面的结果:一次确认、从列表中选中的一项、一份填好的表单。泛型 push<bool> 记录了你期望取回的内容。
import 'package:flutter/material.dart';
Future<void> openDetail(BuildContext context) async {
final added = await Navigator.push<bool>(
context,
MaterialPageRoute<bool>(
builder: (context) {
return const DetailScreen(
productName: 'Headphones',
);
},
),
);
if (!context.mounted) return;
final message = (added ?? false)
? 'Product added to cart'
: 'No product added';
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}