管理多个页面时有两个核心概念和类:Route和 Navigator。 一个route是一个屏幕或页面的抽象,Navigator是管理route的Widget。Navigator可以通过route入栈和出栈来实现页面之间的跳转。
1. 导航跳转及返回(带传值)
- 基础跳转及返回
// 跳转
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const DetailScreen(); // 详情页面类
}));
// 返回
Navigator.pop(context);
- 导航页面传值及返回传值
简单routes路由传值,结合 3.1中的简单路由集合。
// 传值,第一种 values是各种类型
Navigator.pushNamed(
context,
"/login",
arguments: values
);
// 下个页面获取值
@override
Widget build(BuildContext context) {
// 只能在build中获取参数值
final args = ModalRoute.of(context)!.settings.arguments as ScreenArguments;
return Scaffold(
appBar: AppBar(
title: Text(args.title),
),
body: Center(
child: Text(args.message),
),
);
}
2. 导航返回拦截
监控返回按钮点击,flutter 提供 willPopScope来实现返回按钮拦截。
Widget build(BuildContext context) {
var name = ModalRoute.of(context)!.settings.arguments as String;
return Scaffold(
appBar: AppBar(
title: Text("seconds"),
),
// 在顶部元素设置willPopScope
body: WillPopScope(
onWillPop: () async {
print("you print is back");
return true;
},
child: Container(
child: Text("you send is $youName"),
),
),
);
}
- onWillPop是一个回调函数,当用户点击返回按钮时被调用,如果return true, 则同意返回
- child 则是显示的界面
3. 设置路由routes
1 设置简单路由集合
设置routes, 我这边单独设置一个routes.dart文件
// routes.dart
Map<String, Widget Function(BuildContext)> routes = {
"/login": (context) => loginController(),
'/main': (context) => MainTabBarView(),
'/verifyInfo': (context) => VerifyInfoController(), // 我的页面- 认证信息
'/pwdManager': (context) => PwdManagerController(), // 我的页面- 密码管理
'/webviewLoadHTTP': (context) => WebviewLoadHTTP(), // webView加载HTTP URL
'/webviewLoadHTML': (context) => WebviewLoadHTML(), // webView加载HTML
'/checkUpdate': (context) => CheckUpdateController(), // 我的页面- 检查版本更新
};
在main.dart中
// main.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Global.theme,
brightness: Brightness.light,
),
debugShowCheckedModeBanner: false,
routes: routes, // 设置routes
home: loginController(),
);
}
}
优点:页面路由只在routes.dart中设置,方便查看。
缺点:这种方式往下一个页面传值,需要在下一个页面加载时才能获取到这个值。如果下个页面setState()时,值也会刷新一下,如果传递的时id,通过id在网络获取详情信息时,刷新页面时也会重新请求数据,请求完再刷新,就会造成死循环。
- 通过构造函数传值。
在详情页面,去除构造函数的const类型,设置构造函数参数
class DetailDelegateController extends StatefulWidget {
DetailDelegateController({
Key? key,
@required this.trustInfoDic,
}) : super(key: key);
final Map<String, dynamic>? trustInfoDic;
@override
_DetailDelegateControllerState createState() => _DetailDelegateControllerState();
}
class _DetailDelegateControllerState extends State<DetailDelegateController> {
var trustInfo;
@override
void initState() {
// 初始化时请求网络。
super.initState();
trustInfo = widget.trustInfoDic;
String trustId = trustInfo["id"] ?? "";
getTrustDetailFromServer(trustId, context);
}
}
跳转:
Navigator.push(context,
MaterialPageRoute(
builder: (context) => DetailDelegateController(trustInfoDic: tapTrust,),
),
);
缺点: 无法使用routes设置。
- 使用onGenerateRoute提取参数后传给相应Widget
在main.dart中,隐藏routes参数,使用onGenerateRoute方法。
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Global.theme,
brightness: Brightness.light,
),
debugShowCheckedModeBanner: false,
// routes: routes,
onGenerateRoute: (RouteSettings settings) {
print('build route for ${settings.name}');
var routes = routeWithSetting(settings); // 此方法在routes.dart
WidgetBuilder builder = routes[settings.name]!;
return MaterialPageRoute(builder: (ctx) => builder(ctx), settings: settings);
},
home: loginController(),
);
}
// routes.dart
Map<String, Widget Function(BuildContext)> routeWithSetting(RouteSettings settings) {
return {
"/login": (context) => loginController(),
'/main': (context) => MainTabBarView(),
'/verifyInfo': (context) => VerifyInfoController(), // 我的页面- 认证信息
'/pwdManager': (context) => PwdManagerController(), // 我的页面- 密码管理
'/webviewLoadHTTP': (context) => WebviewLoadHTTP(), // webView加载HTTP URL
'/detailDelegate': (context) => DetailDelegateController(trustInfoDic: settings.arguments as Map<String, dynamic>,), // 我的页面,显示委托人详情
};
}
使用pushName传值
Navigator.pushNamed(context, "/detailDelegate", arguments: dataSourceList[index]);
详情页面类似于构造函数赋值。