Flutter中的导航简介

One of the most fundamental aspects of a mobile app is for the user to be able to move between different pages. Luckily for us, Flutter makes creating routes and moving between screens incredibly easy, especially when compared to many front-end solutions.

移动应用程序最基本的方面之一是使用户能够在不同页面之间移动。 对我们来说幸运的是,Flutter使创建路线和在屏幕之间移动变得异常容易,特别是与许多前端解决方案相比。

项目文件设置 (Project File Setup)

For our example, we’re just going to have 4 screens, our main.dart file, and break the navbar into its own file.

对于我们的示例,我们将只有4个屏幕,即我们的main.dart文件,并将导航栏分成自己的文件。

* screens 📂
  * account_screen.dart
  * balance_screen.dart
  * transfer_screen.dart
  * welcome_screen.dart
* main.dart
* navbar.dart

命名路线 (Naming Routes)

While you would want to break each route into its own file in most cases, we’ll put them in our main.dart for now.

尽管在大多数情况下,您希望将每条路由分成自己的文件,但我们现在将它们放置在main.dart中。

In our MaterialApp we can set the routes map, which is a list of key/value pairs. Each item in this map links a string value to a callback function that returns the page we want rendered. The point of this is to speed up development by letting us toss around something like 'welcome_screen' whenever we need a new page, instead of the full (context) => WelcomeScreen().

在我们的MaterialApp我们可以设置routes图,这是键/值对的列表。 此映射中的每个项目都将字符串值链接到回调函数,该回调函数返回我们要呈现的页面。 这样做的目的是通过在需要新页面'welcome_screen'不是完整的(context) => WelcomeScreen() ,让我们在'welcome_screen''welcome_screen'东西之间折腾来加快开发速度。

To set our home page we can either use the MaterialApp’s home property or the initialRoute property. They effectively do the same thing but home takes the class itself, like WelcomeScreen(), and initialRoute takes the key from our routes map. You can’t use both since that confuses the compiler.

要设置主页,我们可以使用MaterialApphome属性或initialRoute属性。 他们有效地执行了相同的操作,但是home本身接受了类,例如WelcomeScreen() ,而initialRoute从我们的routes图中获取了键。 您不能同时使用两者,因为这会使编译器感到困惑。

main.dart
main.dart
import 'package:flutter/material.dart';
import './screens/welcome_screen.dart';
import './screens/account_screen.dart';
import './screens/balance_screen.dart';
import './screens/transfer_screen.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigation Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
       home: WelcomeScreen(), 
       routes: {
        'welcome_screen': (context) => WelcomeScreen(),
        'account_screen': (context) => AccountScreen(),
        'balance_screen': (context) => BalanceScreen(),
        'transfer_screen': (context) => TransferScreen()
    });
  }
}

That works fine, but you may end up typing each of these routes often and just using strings will make it hard to debug when you make the slightest typo. Instead it would make our code a bit less fragile to store each key in a static id variable in each class and just access that id. This will also give us the benefit of VSCode’s IntelliSense and help figuring out why a page may be unavailable.

效果很好,但是您可能最终会经常键入这些路由中的每一个,而使用字符串将使您在进行丝毫打字错误时难以调试。 取而代之的是,将每个键存储在每个类的静态id变量中并仅访问该id,将使我们的代码不那么脆弱。 这也将使我们受益于VSCode的IntelliSense,并有助于弄清为什么页面不可用。

Each screen in our example is the same, beside the id and the text widget. We’re also setting out bottom navbar to a widget that we’ll create later.

在我们的示例中,每个屏幕都相同,除了id和text小部件。 我们还将底部导航栏设置为稍后将创建的小部件。

welcome_screen.dart
welcome_screen.dart
import 'package:flutter/material.dart';
import '../navbar.dart';

class WelcomeScreen extends StatelessWidget {
  static const String id = 'welcome_screen';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        bottomNavigationBar: Navbar(),
        child: Text('Welcome'),
      ),
    );
  }
}

Now we can replace our string with each screen’s id. Notice that we’re accessing it without actually calling the class itself.

现在,我们可以将字符串替换为每个屏幕的ID。 注意,我们在访问它时并未实际调用类本身。

main.dart
main.dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(initialRoute: WelcomeScreen.id, routes: {
      WelcomeScreen.id: (context) => WelcomeScreen(),
      AccountScreen.id: (context) => AccountScreen(),
      BalanceScreen.id: (context) => BalanceScreen(),
      TransferScreen.id: (context) => TransferScreen()
    });
  }
}

推和弹出 (Push and Pop)

Unlike with front-end web development, mobile routing is based on ‘stacking’ screens on top of each other. When we navigate from the welcome screen to the account screen, we’re not really changing pages but adding our account screen onto our stack, thus covering the previous page. To go back to the welcome screen, we would just need to destroy, or pop off, the uppermost layer revealing the already rendered page beneath it.

与前端Web开发不同,移动路由基于彼此叠加的“堆叠”屏幕。 当我们从欢迎屏幕导航到帐户屏幕时,我们实际上并不是在更改页面,而是将帐户屏幕添加到堆栈中,从而覆盖了上一页。 要返回到欢迎屏幕,我们只需要破坏或pop最上层,以显示其下面已渲染的页面。

There are quite a few different methods on Navigator to do this, which you can fully explore here. The main two we need are pushNamed to add to our stack and pop to remove the latest layer. pop just needs our build’s context and push methods needs the context and the page’s key we’ve setup in our routes.

Navigator上有很多不同的方法可以执行此操作,您可以在此处充分探索。 我们需要的主要两个是pushNamed以添加到堆栈中,然后pop以删除最新层。 pop仅需要我们构建的contextpush方法则需要context和我们在路由中设置的页面密钥。

Any method appended with Named is for when we’ve set up our routes in the MaterialApp, otherwise you could pass in the callback itself instead of our keys.

当我们在MaterialApp设置路线时,将使用Named附加的任何方法,否则您可以传入回调本身而不是键。

navbar.dart
导航栏
import 'package:flutter/material.dart';
import './screens/account_screen.dart';
import './screens/balance_screen.dart';
import './screens/transfer_screen.dart';

class Navbar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          FlatButton(
              onPressed: () => Navigator.pop(context),
              child: Icon(Icons.arrow_left, color: Colors.white, size: 40)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, BalanceScreen.id),
              child: Icon(Icons.account_balance, color: Colors.white)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, TransferScreen.id),
              child: Icon(Icons.sync, color: Colors.white)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, AccountScreen.id),
              child: Icon(Icons.account_circle, color: Colors.white)),
        ],
      ),
    );
  }
}

结论 (Conclusion)

Yet again when it comes to routing and navigation Flutter really shines in efficiency and ease of use. Hopefully this short tutorial was helpful in understanding this new technology.

再有,在路由和导航方面,Flutter确实在效率和易用性方面大放异彩。 希望这篇简短的教程对理解这项新技术有所帮助。

翻译自: https://www.digitalocean.com/community/tutorials/flutter-navigation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值