移动应用程序最基本的方面之一是让用户能够在不同的页面之间移动。对我们来说幸运的是,Ffltter让创建路线和在屏幕之间移动变得非常容易,特别是与许多前端解决方案相比。
项目文件设置
对于我们的例子,我们将有4个屏幕,我们的main.dart
文件,并将导航栏分成自己的文件。
1* screens 📂
2 * account_screen.dart
3 * balance_screen.dart
4 * transfer_screen.dart
5 * welcome_screen.dart
6* main.dart
7* navbar.dart
命名路径
虽然在大多数情况下,您可能希望将每条路径分解到各自的文件中,但现在我们将把它们放在我们的`main.dart‘中。
在我们的MaterialApp
中,我们可以设置routes
映射,它是键/值对的列表。该映射中的每一项都将一个字符串值链接到一个回调函数,该回调函数返回我们希望呈现的页面。这样做的目的是为了加快开发速度,只要我们需要一个新页面,就允许我们抛出一些类似于欢迎屏幕‘’的东西,而不是完整的
(上下文)=>WelcomeScreen()`。
要设置主页,我们可以使用MaterialApp
的home
属性或initialRoute
属性。它们实际上做了同样的事情,但是home
接受类本身,就像WelcomeScreen()
一样,而initialRoute
从我们的routes
映射中接受键。你不能同时使用这两个,因为这会混淆编译器。
1[label main.dart]
2import 'package:flutter/material.dart';
3import './screens/welcome_screen.dart';
4import './screens/account_screen.dart';
5import './screens/balance_screen.dart';
6import './screens/transfer_screen.dart';
7
8void main() => runApp(MyApp());
9
10class MyApp extends StatelessWidget {
11 @override
12 Widget build(BuildContext context) {
13 return MaterialApp(
14 title: 'Navigation Demo',
15 home: MyHomePage(),
16 );
17 }
18}
19
20class MyHomePage extends StatefulWidget {
21 @override
22 _MyHomePageState createState() => _MyHomePageState();
23}
24
25class _MyHomePageState extends State<MyHomePage> {
26 @override
27 Widget build(BuildContext context) {
28 return MaterialApp(
29 home: WelcomeScreen(),
30 routes: {
31 'welcome_screen': (context) => WelcomeScreen(),
32 'account_screen': (context) => AccountScreen(),
33 'balance_screen': (context) => BalanceScreen(),
34 'transfer_screen': (context) => TransferScreen()
35 });
36 }
37}
这样做很好,但是您可能会经常输入这些路由,并且如果只使用字符串,即使您输入了最轻微的输入错误,也很难进行调试。相反,将每个键存储在每个类中的静态id变量中并仅访问该id会使我们的代码不那么脆弱。这也会给我们带来VSCode的智能感知的好处,并有助于找出页面不可用的原因。
除了id和文本小部件之外,我们示例中的每个屏幕都是相同的。我们还为稍后创建的小部件设置了底部导航栏。
1[label welcome_screen.dart]
2import 'package:flutter/material.dart';
3import '../navbar.dart';
4
5class WelcomeScreen extends StatelessWidget {
6 static const String id = 'welcome_screen';
7
8 @override
9 Widget build(BuildContext context) {
10 return Scaffold(
11 body: Center(
12 bottomNavigationBar: Navbar(),
13 child: Text('Welcome'),
14 ),
15 );
16 }
17}
现在,我们可以用每个屏幕的id替换字符串。请注意,我们访问它时并没有实际调用类本身。
1[label main.dart]
2class _MyHomePageState extends State<MyHomePage> {
3 @override
4 Widget build(BuildContext context) {
5 return MaterialApp(initialRoute: WelcomeScreen.id, routes: {
6 WelcomeScreen.id: (context) => WelcomeScreen(),
7 AccountScreen.id: (context) => AccountScreen(),
8 BalanceScreen.id: (context) => BalanceScreen(),
9 TransferScreen.id: (context) => TransferScreen()
10 });
11 }
12}
推送和弹出
与前端网络开发不同,移动路由是基于将屏幕堆叠在一起的。当我们从欢迎屏幕导航到帐户屏幕时,我们实际上并不是在更改页面,而是将帐户屏幕添加到堆栈中,从而覆盖了前一页。要返回欢迎屏幕,我们只需销毁或弹出
显示其下方已经呈现的页面的最上面一层。
在Navigator
上有很多不同的方法可以做到这一点,你可以充分探索here.我们需要的两个主要参数是presNamed
用于添加到堆栈中,以及op
用于移除最新的层。op
只需要我们构建的Conext
和Push
方法就需要Conext
和我们在路由中设置的页面密钥。
任何带有Named
的方法都是当我们在MaterialApp
中设置了我们的路由时使用的,否则您可以传入回调本身,而不是我们的key。
1[label navbar.dart]
2import 'package:flutter/material.dart';
3import './screens/account_screen.dart';
4import './screens/balance_screen.dart';
5import './screens/transfer_screen.dart';
6
7class Navbar extends StatelessWidget {
8 @override
9 Widget build(BuildContext context) {
10 return Container(
11 color: Colors.red,
12 child: Row(
13 mainAxisAlignment: MainAxisAlignment.spaceAround,
14 children: <Widget>[
15 FlatButton(
16 onPressed: () => Navigator.pop(context),
17 child: Icon(Icons.arrow_left, color: Colors.white, size: 40)),
18 FlatButton(
19 onPressed: () => Navigator.pushNamed(context, BalanceScreen.id),
20 child: Icon(Icons.account_balance, color: Colors.white)),
21 FlatButton(
22 onPressed: () => Navigator.pushNamed(context, TransferScreen.id),
23 child: Icon(Icons.sync, color: Colors.white)),
24 FlatButton(
25 onPressed: () => Navigator.pushNamed(context, AccountScreen.id),
26 child: Icon(Icons.account_circle, color: Colors.white)),
27 ],
28 ),
29 );
30 }
31}
结论
再说一次,当涉及路线和导航时,颤动在效率和易用性方面确实闪耀着光芒。希望这篇简短的教程有助于理解这项新技术。