Flutter路由管理插件stack_router的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter路由管理插件stack_router的使用

Stack router 使用 IndexedStack 来在不同的小部件之间进行路由。它们自带类似核心 Flutter UI 库提供的骨架、应用栏和消息提示。

使用

import 'package:stack_router/stack_router.dart';

class ExampleStackRoutes {
  static const String firstRoute = 'firstRoute';
  static const String secondRoute = 'secondRoute';
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Material(
      child: StackRouter(
        initialRoute: ExampleStackRoutes.firstRoute,
        builder: (router) {
          return [
            StackRoute(
              route: ExampleStackRoutes.firstRoute,
              child: Center(
                child: ElevatedButton(
                  onPressed: () {
                    router.pushRoute(ExampleStackRoutes.secondRoute);
                  },
                  child: const Text(
                    "Go to second route",
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
            StackRoute(
              route: ExampleStackRoutes.secondRoute,
              child: StackRouterScaffold(
                appBar: const StackRouterAppBar(
                  title: Text("I'm a Title", style: TextStyle(fontSize: 24)),
                ),
                child: Container(
                  color: Colors.blue,
                  alignment: Alignment.center,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Text(
                        "I'm the second route",
                        style: TextStyle(
                          color: Colors.white,
                        ),
                      ),
                      const Padding(padding: EdgeInsets.only(top: 16)),
                      ElevatedButton(
                        style: ButtonStyle(
                          backgroundColor:
                              MaterialStateProperty.all(Colors.white),
                        ),
                        onPressed: () {
                          router.showSnackBar(
                            snackBar: const StackRouterSnackBar(
                              title: Text(
                                "I'm a snackbar!",
                                style: TextStyle(color: Colors.white),
                              ),
                            ),
                          );
                        },
                        child: const Text(
                          "Show snack bar",
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ];
        },
      ),
    );
  }
}

在这个例子中,第一个路由包含一个按钮,当按下时,它会使用 router.pushRoute API 导航到第二个路由。

基本的路由导航API包括:

  • pushRoute(String route) - 将给定的路由推到导航堆栈的顶部。
  • popRoute([String? route]) - 弹出给定的路由(默认为当前路由)从导航堆栈。

StackRouterActions

类似于 Flutter Material 的 ScaffoldMessenger,任何在 StackRouterScaffold 下的子组件都可以通过由 InheritedWidget 提供的 StackRouterActions 来操作 stack router

这使得从当前路由显示消息提示和更改路由变得容易。

class SecondRoute extends StatelessWidget {
  @override
  build(context) {
    return StackRouterScaffold(
      child: Center(
        child: ElevatedButton(
          style: ButtonStyle(
            backgroundColor:
                MaterialStateProperty.all(Colors.white),
          ),
          onPressed: () {
            StackRouterActions.of(context).showSnackBar(
              snackBar: const StackRouterSnackBar(
                title: Text(
                  "I'm a snackbar!",
                  style: TextStyle(color: Colors.white),
                ),
              ),
              actions: [
                TextButton(
                  child: Text('Go back'),
                  onPressed: () {
                    StackRouterActions.of(context).popRoute();
                  }
                )
              ]
            );
          },
          child: const Text(
            "Show snack bar",
            style: TextStyle(color: Colors.black),
          ),
        ),
      ),
    );
  }
}

消息提示

消息提示按路由排队,并且可以使用路由器消息提示API显示或隐藏:

  • showSnackBar({ required StackRouterSnackBar snackBar, String? route }) - 在提供的路由上显示消息提示(默认为当前路由)。
  • hideSnackBar({ String? route }) - 清除提供的路由上的当前消息提示(默认为当前路由)。
  • clearSnackBars({ String? route }) - 清除给定路由上的所有消息提示(默认为当前路由)。

以下示例中,当按钮被按下时,两个消息提示将排队到当前路由:

class SecondRoute extends StatelessWidget {
  @override
  build(context) {
    return StackRouterScaffold(
      child: Center(
        child: ElevatedButton(
          style: ButtonStyle(
            backgroundColor:
                MaterialStateProperty.all(Colors.white),
          ),
          onPressed: () {
            StackRouterActions.of(context).showSnackBar(
              snackBar: const StackRouterSnackBar(
                title: Text(
                  "I'm a snackbar!",
                  style: TextStyle(color: Colors.white),
                ),
              ),
            );
            StackRouterActions.of(context).showSnackBar(
              snackBar: const StackRouterSnackBar(
                title: Text(
                  "I'm another snackbar!",
                  style: TextStyle(color: Colors.white),
                ),
              ),
            );
          },
          child: const Text(
            "Show snack bar",
            style: TextStyle(color: Colors.black),
          ),
        ),
      ),
    );
  }
}

你也可以在不同于当前路由的其他路由上显示消息提示:

class SecondRoute extends StatelessWidget {
  @override
  build(context) {
    return StackRouterScaffold(
      child: Center(
        child: ElevatedButton(
          style: ButtonStyle(
            backgroundColor:
                MaterialStateProperty.all(Colors.white),
          ),
          onPressed: () {
            StackRouterActions.of(context).showSnackBar(
              snackBar: const StackRouterSnackBar(
                title: Text(
                  "I'm a snackbar!",
                  style: TextStyle(color: Colors.white),
                ),
              ),
            );
            StackRouterActions.of(context).showSnackBar(
              snackBar: const StackRouterSnackBar(
                route: ExampleStackRoutes.firstRoute,
                title: Text(
                  "I'm a snackbar for another route!",
                  style: TextStyle(color: Colors.white),
                ),
              ),
            );
          },
          child: const Text(
            "Show snack bar",
            style: TextStyle(color: Colors.black),
          ),
        ),
      ),
    );
  }
}

持久化路由

Stack routers 将在路由列表中指定的小部件传递给 IndexedStack 小部件,该小部件选择要显示的路由。由于路由由 IndexedStack 管理,因此具有某些有趣的特性,比如能够预热并持久化路由:

StackRoute(
  route: ExampleStackRoutes.secondRoute,
  persist: true,
  child: Center(
    child: const Text(
      "Second route",
      style: TextStyle(color: Colors.white),
    ),
  ),
);

默认情况下,堆栈路由器中的路由不会构建,直到它被推送到堆栈上。所有已推送的路由都保留在 StackRouter 历史记录中并保持持久状态,以便当你推送到第二个路由并弹回到第一个路由时,它仍然是相同的组件实例,并保留了所有临时状态,如表单数据或用户在导航离开之前对路由所做的更改。

如果你希望在导航到特定路由之前就预热该路由,你可以通过在路由上指定 persist: true 来实现,这样它将在 StackRouter 第一次实例化时乐观地构建。这对于在流程中很可能被导航到并且由于网络数据需求或深层构建树而较慢构建的路由非常有用。

构建模态流

Stack routers 对于构建模态流和向导非常有用,这些通常可以在桌面网页平台上看到。要使用 StackRouter 构建模态流,请查看 modal_stack_router

// 示例代码位于 https://github.com/danReynolds/stack_router/blob/master/example/lib/main.dart

更多关于Flutter路由管理插件stack_router的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter路由管理插件stack_router的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,stack_router 是一个用于管理路由的插件,它允许开发者以堆栈的方式管理页面路由,从而可以更灵活地控制页面的显示和隐藏。下面是一个关于如何使用 stack_router 的代码示例。

首先,确保你已经在 pubspec.yaml 文件中添加了 stack_router 的依赖:

dependencies:
  flutter:
    sdk: flutter
  stack_router: ^最新版本号 # 替换为实际的最新版本号

然后,运行 flutter pub get 来安装依赖。

接下来,我们来看一个完整的示例,展示如何使用 stack_router 进行路由管理。

主文件 main.dart

import 'package:flutter/material.dart';
import 'package:stack_router/stack_router.dart';
import 'routes/home_page.dart';
import 'routes/details_page.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Stack Router Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: StackRouter(
        routes: [
          StackRoute(
            path: '/',
            builder: (context) => HomePage(),
          ),
          StackRoute(
            path: '/details/:id',
            builder: (context, params) => DetailsPage(id: params['id']!),
          ),
        ],
        unknownRouteBuilder: (context, settings) {
          return Scaffold(
            appBar: AppBar(
              title: Text('404 Not Found'),
            ),
            body: Center(
              child: Text('Page not found'),
            ),
          );
        },
      ),
    );
  }
}

routes/home_page.dart

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.of(context).pushNamed('/details/123');
          },
          child: Text('Go to Details Page'),
        ),
      ),
    );
  }
}

routes/details_page.dart

import 'package:flutter/material.dart';

class DetailsPage extends StatelessWidget {
  final String id;

  DetailsPage({required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Details Page'),
      ),
      body: Center(
        child: Text('Details for item $id'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).pop();
        },
        tooltip: 'Back',
        child: Icon(Icons.arrow_back),
      ),
    );
  }
}

解释

  1. main.dart

    • 使用 MaterialApp 作为根应用。
    • 使用 StackRouter 作为路由管理器,定义了两个路由:根路由 (/) 和详情路由 (/details/:id)。
    • unknownRouteBuilder 用于处理未知路由,返回一个404页面。
  2. routes/home_page.dart

    • HomePage 是一个简单的页面,包含一个按钮,点击按钮会导航到详情页面。
  3. routes/details_page.dart

    • DetailsPage 接收一个 id 参数,并显示详情信息。
    • 包含一个返回按钮,点击按钮会返回到前一个页面。

通过上述代码,你可以使用 stack_router 来管理Flutter应用中的页面路由,实现堆栈式的页面导航。

回到顶部