flutter系列之:Navigator的高级用法

简介: 上篇文章我们讲到了flutter中navigator的基本用法,我们可以使用它的push和pop方法来进行Router之间的跳转。在flutter中一个Router就是一个widget,但是在Android中,一个Router就是Activity,在IOS中,一个Router是一个ViewController。Router除了之前讲过的push和pop方法之外,还有一些更加高级的用法,一起来看看吧。

简介

上篇文章我们讲到了flutter中navigator的基本用法,我们可以使用它的push和pop方法来进行Router之间的跳转。

在flutter中一个Router就是一个widget,但是在Android中,一个Router就是Activity,在IOS中,一个Router是一个ViewController。

Router除了之前讲过的push和pop方法之外,还有一些更加高级的用法,一起来看看吧。

named routes

虽然在flutter中navigator将routers以stack的形式进行存储,能做的也只是push和pop操作,但是事实上Router是可以有名字的。

想想也是,如果Router没有名字的话,那么如何顺利进行跳转呢?不可能每次都new一个Router出来吧。

navigator有一个方法叫做Navigator.pushNamed()用来将带名字的Router压入堆栈,我们来看下它的定义:

static Future<T?> pushNamed<T extends Object?>(
    BuildContext context,
    String routeName, {
    Object? arguments,
  }) {
    return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
  }

这个方法需要传入一个context和对应的routeName,同时还可以带一些参数。

那么怎么用这个方法呢?

首先我们需要定义一些Router,比如说在创建MaterialApp的时候可以传入routes参数,来设置named Routers:

MaterialApp(
  title: '这是named Routers',
  initialRoute: '/firstPage',
  routes: {
    '/firstPage': (context) => const FirstPage(),
    '/secondPage': (context) => const SecondPage(),
  },
)

上面的代码中我们分别定了两个routers,分别是firstPage和secondPage,他们分别对应一个自定义的widget。

定义好Router之后,我们就可以向下面这样使用了:

onPressed: () {
  Navigator.pushNamed(context, '/secondPage');
}

如果要返回第一个页面的话,那么可以调用Navigator.pop方法来实现:

onPressed: () {
  Navigator.pop(context);
}

给named route传参数

在上一节我们讲到pushNamed的时候,还介绍了它还可以接收参数arguments。从定义上可以看到arguments的类型是Object对象,也就是说任何对象都可以作为named route的参数。

那么我们先定义一个对象如下:

class TestArguments {
  final String name;
  final String description;
  TestArguments(this.name, this.description);
}

接下来我们需要创建一个能够接受这个参数的Routers。

因为所有的Routers都是Widget,所以我们需要创建一个Widget,并在这个widget内部接收传入的参数。

在flutter中有两种传递参数的方式,你可以使用ModalRoute.of(),也可以使用onGenerateRoute()。

我们先来看下ModalRoute.of的定义:

static ModalRoute<T>? of<T extends Object?>(BuildContext context) {
    final _ModalScopeStatus? widget = context.dependOnInheritedWidgetOfExactType<_ModalScopeStatus>();
    return widget?.route as ModalRoute<T>?;
  }

它接收一个context参数,然后返回一个route对象。

具体的用法如下:

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});
  static const routeName = '/firstPage';
  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as TestArguments;
    return Scaffold(
      appBar: AppBar(
        title: Text(args.name),
      ),
      body: Center(
        child: Text(args.description),
      ),
    );
  }
}

除了使用ModalRoute之外,还可以在onGenerateRoute()方法中进行参数传递。onGenerateRoute是在Route生成的时候触发的:

MaterialApp(
  onGenerateRoute: (settings) {
    if (settings.name == FirstPage.routeName) {
      final args = settings.arguments as TestArguments;
      return MaterialPageRoute(
        builder: (context) {
          return TestArguments(
            title: args.title,
            message: args.message,
          );
        },
      );
    }
    return null;
  },
)

onGenerateRoute接收一个settings对象,我们需要在settings对象中设置对应的name和arguments属性。所以我们需要这样调用:

Navigator.pushNamed(
      context,
      FirstPage.routeName,
      arguments: TestArguments(
        '测试',
        '这是一个named Route',
      ),
    );

从Screen返回值

有时候我们需要从一个Screen返回到之前的Screen,并且不是简单的返回,我们还希望知道前一个screen返回了什么结果,然后可以根据前一个screen返回的不同结果来进行不同的处理。

这个时候就需要用到Navigator.pop的传参功能了。

比如我们在第一个页面中点击了按钮,跳转到第二个页面:

final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const SecondScreen()),
    );

这里我们使用到了Navigator.push方法,并且返回了一个result的值。

我们可以使用这个值来进行一些逻辑判断。

那么这个result的值是哪里传递过来的呢?

没错,就是SecondScreen中的Navigator.pop方法:

Navigator.pop(context, 'Yes');

这里的’Yes’就会传递给result供我们进行逻辑判断。

向Screen传值

有时候我们需要在页面跳转的过程中传递一些参数,那么怎么才能实现Screen之间的参数传递呢?

因为在flutter中所有的Routers都是Widget,所以我们可以在跳转到新的页面的时候直接将参数以构造函数的方式传递给Routers Widget。

比如我们有下面的Screen Widget:

class NameScreen extends StatelessWidget {
  const NameScreen({super.key, required this.name});
  final String name;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('NameScreen'),
      ),
      body: 
      ...
      ;
  }
}

想要传值给它,可以在onTap方法中这样写:

onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => NameScreen(name: 'what is your name?'),
          ),
        );

总结

以上就是Navigator的更加高级的用法,我们可以通过Navigator来进行数据传递等操作,从而实现更加复杂的页面功能。


相关文章
Flutter笔记:AnimationMean、AnimationMax 和 AnimationMin 三个类的用法
Flutter笔记:AnimationMean、AnimationMax 和 AnimationMin 三个类的用法
92 3
|
18天前
|
容器
Flutter &&鸿蒙next中的 Stack 和 Positioned 用法详解
在 Flutter 中,Stack 和 Positioned 是创建层叠布局和灵活定位元素的常用组件。Stack 可以将多个子组件叠加在一起,允许子组件相互重叠;Positioned 用于在 Stack 内部精确控制子组件的位置。本文详细介绍了它们的基本用法、属性和应用场景,包括动画、弹出层和悬浮按钮等。
67 1
|
20天前
|
Dart 安全 编译器
Flutter结合鸿蒙next 中数据类型转换的高级用法:dynamic 类型与其他类型的转换解析
在 Flutter 开发中,`dynamic` 类型提供了灵活性,但也带来了类型安全性问题。本文深入探讨 `dynamic` 类型及其与其他类型的转换,介绍如何使用 `as` 关键字、`is` 操作符和 `whereType&lt;T&gt;()` 方法进行类型转换,并提供最佳实践,包括避免过度使用 `dynamic`、使用 Null Safety 和异常处理,帮助开发者提高代码的可读性和可维护性。
69 1
|
3月前
|
JavaScript 前端开发 Android开发
Flutter笔记:关于WebView插件的用法(下)
Flutter笔记:关于WebView插件的用法(下)
223 5
|
3月前
|
存储 缓存 JavaScript
Flutter笔记:关于WebView插件的用法(上)
Flutter笔记:关于WebView插件的用法(上)
1516 4
|
6月前
|
前端开发 搜索推荐 UED
【Flutter前端技术开发专栏】Flutter中的高级UI组件应用
【4月更文挑战第30天】探索Flutter的高级UI组件,如`TabBar`、`Drawer`、`BottomSheet`,提升应用体验和美观度。使用高级组件能节省开发时间,提供内置交互逻辑和优秀视觉效果。示例代码展示了如何实现底部导航栏、侧边导航和底部弹出菜单。同时,自定义组件允许个性化设计和功能扩展,但也带来性能优化和维护挑战。参考Flutter官方文档和教程,深入学习并有效利用这些组件。
153 0
【Flutter前端技术开发专栏】Flutter中的高级UI组件应用
|
6月前
|
Dart 小程序 前端开发
WebSocket 解析与应用(包含web前端、服务端、小程序、dart/flutter中的用法)
WebSocket 解析与应用(包含web前端、服务端、小程序、dart/flutter中的用法)
767 0
|
6月前
|
开发框架 Java 开发者
Flutter特殊用法介绍
Flutter特殊用法介绍 Flutter是一种开源移动应用程序开发框架,具有高效、快速、美观、灵活等特点。本文将介绍Flutter中的一些特殊用法,帮助开发者更好地使用Flutter进行应用程序开发。
|
Android开发 iOS开发
flutter 路由管理- Navigator的push和pop
Navigator类是flutter一个路由管理的组件,通过一个栈来管理活动路由集合,通常当前屏幕显示的页面就是栈顶的路由。
1074 0
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin