欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > Flutter之路由和导航

Flutter之路由和导航

2025/4/28 11:55:53 来源:https://blog.csdn.net/zouyang920/article/details/147442398  浏览:    关键词:Flutter之路由和导航

目录:

    • 1、flutter路由和导航简介
    • 2、路由的使用
      • 2.1、使用 Navigator
      • 2.2、使用命名路由
      • 2.3、使用路由器
    • 3、应用中添加Tab导航
    • 4、页面跳转一个新页面和回退
    • 5、传递数据到新页面
    • 6、使用 RouteSettings 传递参数

1、flutter路由和导航简介

Flutter 提供了一个完整的系统,用于在屏幕之间导航和处理 深层链接。没有复杂深度链接的小型应用程序可以使用 Navigator,而具有特定深度链接和导航的应用程序 要求还应该使用 Router 来正确处理 Android 和 iOS,并在应用程序运行时与地址栏保持同步 在 Web 上运行。

2、路由的使用

2.1、使用 Navigator

小组件使用正确的过渡将屏幕显示为堆栈 动画。要导航到新屏幕,请通过 route 访问 并调用命令式方法。

child: const Text('Open second screen'),
onPressed: () {Navigator.of(context).push(MaterialPageRoute(builder: (context) => const SecondScreen()),);
},

因为会保留一堆对象(表示历史记录 stack),该方法还接受一个 object。

2.2、使用命名路由

child: const Text('Open second screen'),
onPressed: () {Navigator.pushNamed(context, '/second');
},

/second表示在列表中声明的命名路由。有关完整示例,请按照 Flutter 说明书中的使用命名路由导航 recipe 进行作。MaterialApp.routes

局限性:

  • 尽管命名路由可以处理深度链接,但行为始终相同,并且 无法自定义。当平台收到新的深度链接时,Flutter 将新用户推送到Navigator 上,而不管用户当前位于何处。
  • Flutter 也不支持使用 命名路由。由于这些原因,我们不建议在大多数 应用。

2.3、使用路由器

具有高级导航和路由要求(例如 使用指向每个屏幕的直接链接的 Web 应用程序,或具有多个小组件的应用程序)应使用路由包,例如 go_router 解析路由路径并配置每当应用程序收到 new deep link 的 intent 值。

要使用 Router,请切换到 or 上的构造函数,并为其提供一个配置。路由包, 如 go_router,通常提供路由配置和路由 可以按如下方式使用:

child: const Text('Open second screen'),
onPressed: () => context.go('/second'),

因为像 go_router 这样的包是声明性的,所以它们将始终显示 收到深度链接时的相同屏幕。

go_router的使用案例:
在这里插入图片描述

dependencies:flutter:sdk: fluttergo_router: ^x.y.z  # 替换x.y.z为最新版本号

在这里插入图片描述

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {final _router = GoRouter(initialLocation: '/',routes: [GoRoute(path: '/',builder: (context, state) => HomePage(),),GoRoute(path: '/details',builder: (context, state) => DetailsPage(),),],);return MaterialApp.router(routerConfig: _router,);}
}
  1. 创建页面和导航
    确保你已创建了相应的页面(如HomePage和DetailsPage),这些将作为路由的目标。例如:
class HomePage extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Home')),body: Center(child: ElevatedButton(onPressed: () {context.go('/details'); // 使用context.go进行导航},child: Text('Go to Details'),),),);}
}
  1. 使用参数和嵌套路由(可选)
    你可以在路由中使用参数,并设置嵌套路由:
GoRoute(path: '/user/:id', // 参数使用冒号标记builder: (context, state) {final userId = state.params['id']; // 获取参数值return UserPage(userId: userId); // 将参数传递给页面},routes: [ // 嵌套路由示例GoRoute(path: 'profile', builder: (context, state) => ProfilePage(), ),],
),

在页面中使用参数:

class UserPage extends StatelessWidget {final String userId; // 页面接收参数构造函数或初始化列表赋值方式之一// 构造函数接收参数userId 初始化列表赋值方式也行 如 final String userId; UserPage({Key? key, required this.userId}) : super(key: key); 然后在build中使用userId。 例如显示在文本中:Text('User ID: $userId')。 嵌套路由的使用同理,你可以在ProfilePage中通过context访问嵌套路由的参数。 例如:final profileId = state.params['profileId']; // 在ProfilePage的build方法中使用。 注意这里的state是从context获取的,通常在build方法中通过ModalRoute.of(context).settings来获取。 但由于我们使用了GoRouter,可以直接通过builder的state参数获取。 例如在ProfilePage的build方法中可以直接使用String profileId = state.params['profileId']; 来获取参数。 若要导航到嵌套路由,可以使用context.go('/user/${userId}/profile');。 若要在嵌套路由的页面中使用非嵌套路由的参数,可以通过ModalRoute.of(context).settings.arguments来获取。 但由于我们使用了GoRouter,可以直接通过state参数获取。 若要在嵌套路由中导航,可以使用context.go('profile');(注意没有前导斜杠)。 若要在非嵌套路由中使用嵌套路由的参数,可以在非嵌套路由的页面中通过context.go('/user/${userId}'); 然后在这个路由的builder方法中通过state.subloc获取嵌套路由的状态,例如:StringUserPage({required this.userId}); 

3、应用中添加Tab导航

在这里插入图片描述

import 'package:flutter/material.dart';void main() {runApp(const TabBarDemo());
}class TabBarDemo extends StatelessWidget {const TabBarDemo({super.key});Widget build(BuildContext context) {return MaterialApp(home: DefaultTabController(length: 3,child: Scaffold(appBar: AppBar(bottom: const TabBar(tabs: [Tab(icon: Icon(Icons.directions_car)),Tab(icon: Icon(Icons.directions_transit)),Tab(icon: Icon(Icons.directions_bike)),],),title: const Text('Tabs Demo'),),body: const TabBarView(children: [Icon(Icons.directions_car),Icon(Icons.directions_transit),Icon(Icons.directions_bike),],),),),);}
}

4、页面跳转一个新页面和回退

  • 用 Navigator.push() 跳转到第二个路由
  • 用 Navigator.pop() 回退到第一个路由

5、传递数据到新页面

在这里插入图片描述
在这里插入图片描述

import 'package:flutter/material.dart';class Todo {final String title;final String description;const Todo(this.title, this.description);
}void main() {runApp(MaterialApp(title: 'Passing Data',home: TodosScreen(todos: List.generate(20,(i) => Todo('Todo $i','A description of what needs to be done for Todo $i',),),),),);
}class TodosScreen extends StatelessWidget {const TodosScreen({super.key, required this.todos});final List<Todo> todos;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Todos')),body: ListView.builder(itemCount: todos.length,itemBuilder: (context, index) {return ListTile(title: Text(todos[index].title),// When a user taps the ListTile, navigate to the DetailScreen.// Notice that you're not only creating a DetailScreen, you're// also passing the current todo through to it.onTap: () {Navigator.push(context,MaterialPageRoute(builder: (context) => DetailScreen(todo: todos[index]),),);},);},),);}
}class DetailScreen extends StatelessWidget {// In the constructor, require a Todo.const DetailScreen({super.key, required this.todo});// Declare a field that holds the Todo.final Todo todo;Widget build(BuildContext context) {// Use the Todo to create the UI.return Scaffold(appBar: AppBar(title: Text(todo.title)),body: Padding(padding: const EdgeInsets.all(16),child: Text(todo.description),),);}
}

6、使用 RouteSettings 传递参数

import 'package:flutter/material.dart';class Todo {final String title;final String description;const Todo(this.title, this.description);
}void main() {runApp(MaterialApp(title: 'Passing Data',home: TodosScreen(todos: List.generate(20,(i) => Todo('Todo $i','A description of what needs to be done for Todo $i',),),),),);
}class TodosScreen extends StatelessWidget {const TodosScreen({super.key, required this.todos});final List<Todo> todos;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Todos')),body: ListView.builder(itemCount: todos.length,itemBuilder: (context, index) {return ListTile(title: Text(todos[index].title),// When a user taps the ListTile, navigate to the DetailScreen.// Notice that you're not only creating a DetailScreen, you're// also passing the current todo through to it.onTap: () {Navigator.push(context,MaterialPageRoute(builder: (context) => const DetailScreen(),// Pass the arguments as part of the RouteSettings. The// DetailScreen reads the arguments from these settings.//通过此处来传递参数,其他地方同上settings: RouteSettings(arguments: todos[index]),),);},);},),);}
}class DetailScreen extends StatelessWidget {const DetailScreen({super.key});Widget build(BuildContext context) {final todo = ModalRoute.of(context)!.settings.arguments as Todo;// Use the Todo to create the UI.return Scaffold(appBar: AppBar(title: Text(todo.title)),body: Padding(padding: const EdgeInsets.all(16),child: Text(todo.description),),);}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词