Flutter中的导航介绍

来自菜鸟教程
跳转至:导航、​搜索

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

项目文件设置

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

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

命名路由

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

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

要设置我们的主页,我们可以使用 MaterialApphome 属性或 initialRoute 属性。 他们有效地做同样的事情,但 home 获取类本身,如 WelcomeScreen(),而 initialRoute 从我们的 routes 映射中获取密钥。 您不能同时使用两者,因为这会使编译器感到困惑。

主要.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()
    });
  }
}

这很好用,但是您最终可能会经常键入这些路由中的每一个,并且当您打出最轻微的错字时,仅使用字符串就会使调试变得困难。 相反,将每个键存储在每个类中的静态 id 变量中并仅访问该 id 会使我们的代码不那么脆弱。 这也将使我们受益于 VSCode 的 IntelliSense,并帮助找出页面可能不可用的原因。

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

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'),
      ),
    );
  }
}

现在我们可以用每个屏幕的 id 替换我们的字符串。 请注意,我们在没有实际调用类本身的情况下访问它。

主要.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()
    });
  }
}

推送和弹出

与前端 Web 开发不同,移动路由基于“堆叠”屏幕。 当我们从欢迎屏幕导航到帐户屏幕时,我们并没有真正更改页面,而是将我们的帐户屏幕添加到我们的堆栈中,从而覆盖了前一页。 要返回欢迎屏幕,我们只需要销毁或关闭 pop 最上层,显示其下方已呈现的页面。

Navigator 上有很多不同的方法可以做到这一点,您可以在 此处 充分探索。 我们需要的主要两个是 pushNamed 添加到我们的堆栈和 pop 删除最新的层。 pop 只需要我们构建的 contextpush 方法需要 context 和我们在路由中设置的页面键。

任何带有 Named 的方法都适用于当我们在 MaterialApp 中设置路由时,否则您可以传入回调本身而不是我们的键。

导航栏.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)),
        ],
      ),
    );
  }
}

结论

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