文章目录
- Flutter路由介绍
- 普通路由
- 普通路由传值
- 命名路由
- 将`routes`的配置提到外面(使用的是Map)
- 命名路由传值
- 路由跳转
- 返回上一级路由
- 替换路由
- 返回到根路由
- 返回Tabs后到指定页面
Flutter路由介绍
flutter中的路由通俗就是页面跳转。在Flutter中通过
Navigator
(学过reactjs
或小程序
的小伙伴应该很清楚)组件管理路由导航
Flutter给我们提供了俩种配置路由跳转的方式: 1.基本路由 2.命名路由
普通路由
//格式
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
return const WidgetName();
}));
//search.dart (跳转的页面)
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
const SearchPage({super.key});
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("你好"),
),
body: const Text("搜索页面"),
);
}
}
//home.dart
import 'package:flutter/material.dart';
import 'package:flutter_luyou_learn/pages/search.dart'; //引入SearchPage
...
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 5, vsync: this);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: const Color.fromRGBO(255, 255, 255, 1),
leading: const CircleAvatar(
backgroundImage: NetworkImage(imageUrl(String)),
),
title: ElevatedButton(
onPressed: () {
//主要(路由)
Navigator.of(context)
.push(MaterialPageRoute(builder: (BuildContext context) {
return const SearchPage();
}));
},
child: const Text("搜索"),
),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.red,
labelColor: Colors.red,
unselectedLabelColor: Colors.black,
tabs: const [
Tab(child: Text("直播")),
Tab(child: Text("推荐")),
Tab(child: Text("热门")),
Tab(child: Text("动画")),
Tab(child: Text("影视")),
],
)),
body: TabBarView(
controller: _tabController,
children: const [
Text("直播页"),
Text("推荐页"),
Text("热门页"),
Text("动画页"),
Text("影视页")
],
),
);
}
}
模板的知识请看这里
普通路由传值
跳转传值和调用组件传值的实现方法是一样的
//download.dart (新建一个组件)
import 'package:flutter/material.dart';
class DownloadPage extends StatefulWidget {
final String titleMsg; //像传值一样定义
const DownloadPage({
super.key,
this.titleMsg = "已经缓存视频", //没有传入默认使用这个
});
State<DownloadPage> createState() => _DownloadPageState();
}
class _DownloadPageState extends State<DownloadPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("离线缓存"),
),
// body: const Text("你好"),
body: _DownloadPageBody(
titleMsg: widget.titleMsg, //获取DownloadPage里的属性titleMsg
),
);
}
}
class _DownloadPageBody extends StatelessWidget {
String titleMsg;
_DownloadPageBody({Key? key, required this.titleMsg}) : super(key: key);
Widget build(BuildContext context) {
return Column(
children: [
Container(
width: 100,
height: 50,
decoration: const BoxDecoration(),
child: Text(titleMsg),//显示输出
)
],
);
}
}
//my.dart(关键代码)
ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) {
return const DownloadPage(titleMsg: "测试",);
//return const DownloadPage();
}));
},
child: const Icon(Icons.ads_click),//随意
),
命名路由
//lib.main.dart
import 'package:flutter/material.dart';
import 'package:项目名/pages/tabs.dart';
import 'package:项目名/pages/tabs/my.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
//记住这里不能写const MaterialApp()
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
// home: Tabs(), //去除
routes: {//添加
'/': (context) => const Tabs(),
'/search': (context) => const SearchPage()
},
);
}
}
//lib/pages/tabs.dart
import 'package:flutter/material.dart';
//import 'package:项目名/lib目录下的文件或文件夹'
import 'package:项目名/pages/tabs/home.dart';
import 'package:项目名/pages/tabs/my.dart';
class Tabs extends StatefulWidget {
const Tabs({super.key});
State<Tabs> createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int _currentIndex = 0;
//添加
final List<Widget> _pages = const [HomePage(), MyPage()];
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: _pages[_currentIndex], //修改
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
//index:点击索引值
// print(index);
setState(() {
_currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
BottomNavigationBarItem(
icon: Icon(Icons.my_library_add_outlined), label: "我的")
],
),
);
}
}
//home.dart(命名路由跳转关键代码)
ElevatedButton(
onPressed: () {
//格式:Navigator.pushNamed(context, '/跳转的路径名称');
Navigator.pushNamed(context, '/search'); //命名路由跳转
},
child: const Text("搜索"),
),
将routes
的配置提到外面(使用的是Map)
- 配置主函数
main.dart
//main.dart
import 'package:flutter/material.dart';
import 'package:mmly_learn_flutter/pages/tabs.dart';
import 'package:mmly_learn_flutter/pages/tabs/my.dart';
import 'package:mmly_learn_flutter/pages/tabs/search.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({super.key});
//1、配置路由
Map<String, WidgetBuilder> routes = {
'/': (context) => const Tabs(),
'/search': (context) => const SearchPage()
};
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
//记住这里不能写const MaterialApp()
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
// home: Tabs(),
initialRoute: "/", //初始化路由
onGenerateRoute: (RouteSettings settings) {
//2、配置路由(先把它当作固定格式)
final String? name = settings.name;
final Function? pageContrentBuilder = routes[name];
if (pageContrentBuilder != null) {
if (settings.name != null) {
final Route route = MaterialPageRoute(
builder: (context) => pageContrentBuilder(context,
arguments: settings.arguments));
return route;
}
else {
final Route route = MaterialPageRoute(
builder: (context) => pageContrentBuilder!(context));
return route;
}
}
return null;
},
);
}
}
命名路由传值
跳转页面后传值
//search.dart(找到你需要跳转的页面进行处理)
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
final Map arguments; //在需要传值的页面传入命名路由导航的argments
const SearchPage({super.key, required this.arguments});
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
void initState() {
super.initState();
print(widget.argments); //查看传入的值
// print(widget.arguments['name']);//赋值格式
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("搜索"),
),
);
}
}
//main.dart(配置了routes的组件中,一般是main.dart)
Map<String, WidgetBuilder> routes = {
'/': (context) => const Tabs(),
'/search': (context, {argments}) => SearchPage(arguments: arguments)
};
//home.dart(点击跳转的按钮或者组件)
Navigator.pushNamed(context, '/search', arguments: {"title": "我是命名路由传值", "aid": 10});
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
//1、配置路由
Map<String, WidgetBuilder> routes = {
'/': (context) => const Tabs(),
'/search': (context, {arguments}) => SearchPage(arguments: arguments),
'/login': (context) => const LoginPage(),
'/loginFirst': (context) => const LoginFirstPage()
};
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
//记住这里不能写const MaterialApp()
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
// home: Tabs(),
initialRoute: "/", //初始化路由
onGenerateRoute: (RouteSettings settings) {
//2、配置路由(先把它当作固定格式)
final String? name = settings.name;
final Function? pageContrentBuilder = routes[name];
if (pageContrentBuilder != null) {
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
builder: (context) => pageContrentBuilder(context,
arguments: settings.arguments));
return route;
} else {
final Route route = MaterialPageRoute(
builder: (context) => pageContrentBuilder(context));
return route;
}
}
return null;
},
);
}
}
上图有可能
(context, {argments}) => SearchPage(arguments: arguments)
写成了(context, argments) => SearchPage(arguments: arguments)
settings
:RouteSettings("/...",null)
settings.name
:/...(路径名)
,settings.arguments
:null(传入的值)
路由跳转
我们希望跳转后接着跳转到另一个页面
- 首先实现1次跳转(步骤跟上面的知识一致,我们这里就以login为案例)
//lib/pages/user/login.dart
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("登录页面"),
),
body: Column(
children: [ElevatedButton(onPressed: () {
/*
//返回上一级
Navigator.of(context).pop();
*/}, child: const Text("执行登录"))],
),
);
}
}
//lib/main.dart(路由配置,不一定非是这个文件)
Map<String, WidgetBuilder> routes = {
'/': (context) => const Tabs(),
'/search': (context, {arguments}) => SearchPage(arguments: arguments),
'/login': (context) => const LoginPage() //添加
};
//lib/pages/tabs/home.dart(按自己喜好的文件)
返回上一级路由
//返回上一级
Navigator.of(context).pop();
替换路由
//当然替换的路由路径(/registerSecound)也要添加在Map routes配置中
//注意: 这个方法是将之前的页面进行替换(覆盖),所以之前的页面是销毁的
Navigator.of(context).pushReplacementNamed('/registerSecound')
返回到根路由
- 是使用
Scaffold组件
的appBar
- 通过
Navigator.of(context).pushAndRemoveUntil
进行返回
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) {
return const Tabs(); //返回到根页面
}), (route) => false);
返回Tabs后到指定页面
因为之前学习的时候有
_currentIndex
来指定底部在那个页面,所以
import 'package:flutter/material.dart';
//import 'package:项目名/lib目录下的文件或文件夹'
import 'package:mmly_learn_flutter/pages/tabs/home.dart';
import 'package:mmly_learn_flutter/pages/tabs/my.dart';
class Tabs extends StatefulWidget {
final int index; //添加
const Tabs({super.key, this.index = 0}); //添加
State<Tabs> createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int _currentIndex = 0;
void initState() {
//添加
super.initState();
_currentIndex = widget.index;
} //修改
//添加
final List<Widget> _pages = const [HomePage(), MyPage()];
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
BottomNavigationBarItem(
icon: Icon(Icons.my_library_add_outlined), label: "我的")
],
),
);
}
}
主要是添加(可以在上图代码中查看)
final int index;
this.index = 0
void initState() {...;_currentIndex = widget.index;}
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) {
return const Tabs(index: 1); //注意: 这下标是以0开始的
}), (route) => false);