Flutter页面导航插件simple_navigator的使用

Flutter页面导航插件simple_navigator的使用

简介

SimpleNavigator 是一个轻量级的 Flutter 包,旨在简化命名路由导航。它提供了比复杂的导航解决方案(如 go_router)更简单的 API。

特点

  • 易用的API: 通过简洁的API简化导航代码。
  • 选项卡导航: 使用 SimpleNavigatorTabRoute 轻松集成基于选项卡的导航。
  • 路由守卫: 添加路由守卫以在导航前检查或执行异步任务。
  • URL策略: 启用URL策略以获得更干净、更友好的URL。

开始使用

1. 安装包

pubspec.yaml 文件中添加以下依赖:

dependencies:
  simple_navigator: ^1.0.0

2. 导入包

在 Dart 文件中导入 SimpleNavigator 包:

import 'package:simple_navigator/simple_navigator.dart';

3. 设置路由

main.dart 文件中配置路由:

void main() {
  SN.setRoutes(
    urlStrategy: true,
    splash: (_) => SplashPage(),
    observers: [
      TestObs(),
    ],
    routes: [
      SimpleNavigatorTabRoute(
        path: "/",
        builder: (_, child) => HomePage(
          child: child,
        ),
        tabs: ["/main", "/settings", "/profile"],
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 2000));
          return path;
        },
      ),
      SimpleNavigatorTabRoute(
        path: "/tabs",
        builder: (_, child) => TabsPage(
          child: child,
        ),
        tabs: ["/main", "/settings", "/profile"],
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 20));
          return path;
        },
      ),
      SimpleNavigatorRoute(
        path: "/login",
        builder: (_) => const LoginPage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 2000));
          return path;
        },
      ),
      SimpleNavigatorRoute(
        path: "/feed",
        builder: (_) => const FeedPage(),
      ),
      SimpleNavigatorRoute(
        path: "/main",
        builder: (_) => const MainPage(),
      ),
      SimpleNavigatorRoute(
        path: "/settings",
        builder: (_) => const SettingsPage(),
      ),
      SimpleNavigatorRoute(
        path: "/profile",
        builder: (_) => const ProfilePage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 50));
          return path;
        },
        guardLoadingBuilder: (context) => const Center(
          child: CircularProgressIndicator(),
        ),
      ),
      SimpleNavigatorRoute(
        path: "/sub/:number",
        builder: (_) => const SubPage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 50));
          return path;
        },
      )
    ],
  );
  runApp(const MyApp());
}

4. 实现 MaterialApp

MyApp 类中使用 MaterialApp.router

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      theme: Theme.of(context).copyWith(
        scaffoldBackgroundColor: Colors.amber,
      ),
      routerDelegate: SN.delegate,
      routeInformationParser: SN.parser,
    );
  }
}

示例代码

以下是完整的示例代码:

import 'package:example/feed_page.dart';
import 'package:example/home_page.dart';
import 'package:example/login_page.dart';
import 'package:example/main_page.dart';
import 'package:example/profile_page.dart';
import 'package:example/settings_page.dart';
import 'package:example/splash_page.dart';
import 'package:example/sub_page.dart';
import 'package:example/tabs_page.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:simple_navigator/simple_navigator.dart';

void main() {
  SN.setRoutes(
    urlStrategy: true,
    splash: (_) => SplashPage(),
    observers: [
      TestObs(),
    ],
    routes: [
      SimpleNavigatorTabRoute(
        path: "/",
        builder: (_, child) => HomePage(
          child: child,
        ),
        tabs: ["/main", "/settings", "/profile"],
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 2000));
          return path;
        },
      ),
      SimpleNavigatorTabRoute(
        path: "/tabs",
        builder: (_, child) => TabsPage(
          child: child,
        ),
        tabs: ["/main", "/settings", "/profile"],
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 20));
          return path;
        },
      ),
      SimpleNavigatorRoute(
        path: "/login",
        builder: (_) => const LoginPage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 2000));
          return path;
        },
      ),
      SimpleNavigatorRoute(
        path: "/feed",
        builder: (_) => const FeedPage(),
      ),
      SimpleNavigatorRoute(
        path: "/main",
        builder: (_) => const MainPage(),
      ),
      SimpleNavigatorRoute(
        path: "/settings",
        builder: (_) => const SettingsPage(),
      ),
      SimpleNavigatorRoute(
        path: "/profile",
        builder: (_) => const ProfilePage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 50));
          return path;
        },
        guardLoadingBuilder: (context) => const Center(
          child: CircularProgressIndicator(),
        ),
      ),
      SimpleNavigatorRoute(
        path: "/sub/:number",
        builder: (_) => const SubPage(),
        guard: (path) async {
          await Future.delayed(const Duration(milliseconds: 50));
          return path;
        },
      )
    ],
  );
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      theme: Theme.of(context).copyWith(
        scaffoldBackgroundColor: Colors.amber,
      ),
      routerDelegate: SN.delegate,
      routeInformationParser: SN.parser,
    );
  }
}

class TestObs extends NavigatorObserver {
  [@override](/user/override)
  void didPush(Route route, Route? previousRoute) {
    if (kDebugMode) {
      print("didPush ${route.settings.name}");
    }
    super.didPush(route, previousRoute);
  }

  [@override](/user/override)
  void didPop(Route route, Route? previousRoute) {
    if (kDebugMode) {
      print("didPop ${route.settings.name}");
    }
    super.didPush(route, previousRoute);
  }
}

路由守卫和加载指示器

路由守卫可以在导航前执行一些检查或异步任务。例如,在导航到某些页面之前检查用户是否已登录。如果未登录,则重定向到登录页面。

guard: (path) async {
  await Future.delayed(const Duration(milliseconds: 50));
  return path;
},
guardLoadingBuilder: (context) => const Center(
  child: CircularProgressIndicator(),
),

获取额外参数

可以通过以下方式获取传递给路由的额外参数:

final paramValue = SN.to.getExtraParameter("<param key>");

获取路径参数

可以通过以下方式获取路径参数:

final paramValue = SN.to.getPathParameter("<param key>");

获取查询参数

可以通过以下方式获取查询参数:

final paramValue = SN.to.getQueryParameter("<param key>");

获取当前选项卡

可以通过以下方式获取当前选中的选项卡:

final currentTab = SN.to.currentTab;

选项卡页面示例

class HomePage extends StatefulWidget {
  const HomePage({
    super.key,
    required this.child,
  });

  final Widget child;

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  [@override](/user/override)
  void initState() {
    if (kDebugMode) {
      print("_HomePageState");
    }
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SimpleNavigatorTabsBuilder(
      builder: (context) {
        return Scaffold(
          backgroundColor: Colors.purple,
          bottomNavigationBar: BottomNavigationBar(
            items: const [
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                label: "Home",
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings),
                label: "Settings",
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.person),
                label: "Profile",
              )
            ],
            currentIndex: () {
              if (SN.to.currentTab == "/main") {
                return 0;
              } else if (SN.to.currentTab == "/settings") {
                return 1;
              }
              return 2;
            }(),
            onTap: (index) {
              if (index == 2) {
                SN.to.tab("/profile");
              } else if (index == 1) {
                SN.to.tab("/settings");
              } else {
                SN.to.tab("/main");
              }
            },
          ),
          body: widget.child,
        );
      },
    );
  }
}

更多关于Flutter页面导航插件simple_navigator的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter页面导航插件simple_navigator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


simple_navigator 是一个用于简化 Flutter 页面导航的插件。它提供了一种更简单、更直观的方式来管理页面导航,避免了 Flutter 中默认的 Navigator 的复杂性。使用 simple_navigator,你可以轻松地在页面之间进行跳转,同时还可以管理页面栈。

安装

首先,你需要在 pubspec.yaml 文件中添加 simple_navigator 依赖:

dependencies:
  flutter:
    sdk: flutter
  simple_navigator: ^1.0.0  # 请检查最新版本

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

基本使用

1. 初始化 SimpleNavigator

在你的应用程序的入口处(通常是 main.dart 文件中),初始化 SimpleNavigator 并设置初始页面:

import 'package:flutter/material.dart';
import 'package:simple_navigator/simple_navigator.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SimpleNavigator(
        initialPage: HomePage(),
      ),
    );
  }
}

2. 定义页面

定义你的页面类,每个页面需要继承自 SimplePage

class HomePage extends SimplePage {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 导航到下一个页面
            SimpleNavigator.push(SecondPage());
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends SimplePage {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 返回到上一个页面
            SimpleNavigator.pop();
          },
          child: Text('Go Back'),
        ),
      ),
    );
  }
}

3. 导航操作

使用 SimpleNavigator.push() 进行页面跳转,使用 SimpleNavigator.pop() 返回上一个页面。

// 跳转到下一个页面
SimpleNavigator.push(SecondPage());

// 返回上一个页面
SimpleNavigator.pop();

4. 处理页面返回

你可以重写 SimplePage 中的 onBackPressed 方法来处理返回按钮的逻辑:

class SecondPage extends SimplePage {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            SimpleNavigator.pop();
          },
          child: Text('Go Back'),
        ),
      ),
    );
  }

  @override
  Future<bool> onBackPressed() async {
    // 在这里处理返回按钮的逻辑
    print('Back button pressed');
    return true; // 返回 true 表示允许返回,返回 false 表示阻止返回
  }
}

高级功能

1. 传递参数

你可以在页面跳转时传递参数:

SimpleNavigator.push(SecondPage(), arguments: {'message': 'Hello from HomePage'});

在目标页面中获取参数:

class SecondPage extends SimplePage {
  @override
  Widget build(BuildContext context) {
    final arguments = SimpleNavigator.of(context).arguments;
    final message = arguments['message'];

    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

2. 替换页面

你可以使用 replace 方法来替换当前页面:

SimpleNavigator.replace(ThirdPage());

3. 清空页面栈

你可以使用 popUntilpopAll 方法来清空页面栈:

SimpleNavigator.popUntil((route) => route.isFirst); // 返回到第一个页面
SimpleNavigator.popAll(); // 清空所有页面
回到顶部