問題: flutter優點之一就是可以模塊化開發,但是模塊與模塊之間總是避免不了會出現界面互相跳轉的問題,解決該問題可以有以下方式去解決:
1 使用export
各個模塊之間export出需要給跳轉的頁面,同時需要相互依賴,這樣導致模塊與模塊之間的耦合度過高。
2 在main.date中注冊
flutter在MaterialApp存在routes,每個頁面都可在此進行靜態注冊,注冊完成后,都可使用注冊的名稱進行跳轉,這樣就解決了模塊的耦合問題。但是這要進行跳轉,界面與界面之間傳遞參數,就只能通過RoutSetting中的arguments進行傳遞,同時在傳遞到的頁面也只能在該build的方法里面才能獲取到參數。這樣就存在若進入該頁面需要使用該參數在initState中進行網絡請求,那么這時該參數就無法獲取到了。
3 封裝路由模塊解決
3.1 每個模塊獨自維護路由映射
3.2 在main.date中進行注冊匯總
3.3 在MaterialApp的onGenerateRoute統一處理跳轉
3.4需要使用的模塊依賴app_route,并使用APPNavigator. pushNamed(...)即可實現跳轉
實現代碼如下
創建rout模塊:app_route
APPRoute.data
class APPRoute {
static List<String> moduleNameList = new List<String>();
static Map<String, Function> modulePages = new Map<String, Function>();
static Map<String, Map<String, Function>> allPages = new Map<String, Map<String, Function>>();
static registerModule(String name){
moduleNameList.add(name);
}
static registerModulePage(String name, Map<String, Function> pages){
modulePages.addAll(pages);
allPages.addAll({name:pages});
}
static getAllRoute(){
return modulePages;
}
}
創建APPNavigator代碼統一處理跳轉回退方法
import 'package:flutter/cupertino.dart';
import 'package:paff_route/src/route_arguments.dart';
class APPNavigator {
static pushNamed(BuildContext context, String routeId, {params,popCallback}){
RouteArguments routeArgument = new RouteArguments();
routeArgument.params = params;
Navigator.pushNamed(context, routeId, arguments: routeArgument).then((data){
if(popCallback != null)
popCallback(data);
});
}
static pushReplacement(BuildContext context, String routeId, {params}){
RouteArguments routeArgument = new RouteArguments();
routeArgument.params = params;
Navigator.pushReplacementNamed(context, routeId, arguments: routeArgument);
}
static pushNamedAndRemoveUntil(BuildContext context, String routeId, {params}){
RouteArguments routeArgument = new RouteArguments();
routeArgument.params = params;
Navigator.of(context).pushNamedAndRemoveUntil(routeId,(Route<dynamic> route) => false, arguments: routeArgument);
}
static pushNamedAndRemoveUntilName(BuildContext context, String newRouteId, String oldRouteId,{params}){
RouteArguments routeArgument = new RouteArguments();
routeArgument.params = params;
Navigator.of(context).pushNamedAndRemoveUntil(newRouteId,ModalRoute.withName('/oldRouteId'), arguments: routeArgument);
}
static popUtil(BuildContext context, String routeId ){
Navigator.popUntil(context, ModalRoute.withName(routeId));
}
}
頁面與頁面之間的參數統一包裝在RouteArguments中
class RouteArguments {
Map<String, dynamic> params;
}
其他模塊依賴app_route并維護rout.date文件:
文件實現如下:
String moduleName = "Login";
Map<String, Function> route = <String, Function>{
'/LoginPage': (context, {arguments}) => VBLoginPage(arguments: arguments,),
};
class LoginRoute{
static register(){
AppRoute.registerModulePage(moduleName, route);
}
}
在main.date中初始化
initState -> LoginRoute.register();
最后在onGenerateRoute統一處理
onGenerateRoute: (RouteSettings settings) {
// 統一處理
final String name = settings.name;
final Function pageContentBuilder = AllRoute.getAllRoute()[name];
if (pageContentBuilder != null) {
final Route route = CupertinoPageRoute(
settings: RouteSettings(name: name),
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
}
},
flutter Navigator使用
1 回退:
Navigator.of(context).pop();或Navigator.pop(context);
2 添加:
Navigator.pushName(context,"name");
3 替換:
Navigator.pushReplacementNamed(context, "/screen4")
或
Navigator.popAndPushNamed(context, "/screen4");
pushReplacementNamed 與 popAndPushNamed 的區別在于: popAndPushNamed 能夠執行 Screen2 彈出的動畫與 Screen3 推進的動畫而 pushReplacementNamed 僅顯示 Screen3 推進的動畫。
image.png
4 刪除到指定頁面
Navigator.of(context).pushNamedAndRemoveUntil('/screen4', (Route route) => false);
這里的 (Routeroute) => false 能夠確保刪除先前所有實例。
image.png
5 添加并刪除部分頁面
Navigator.of(context).pushNamedAndRemoveUntil('/screen4', ModalRoute.withName('/screen1'));
image.png
6 回退到指定頁面
Navigator.popUntil(context, ModalRoute.withName('/Dashboard'));
image.png
flutter Navigator 跳轉風格
使用方式: 調用自定義的路由方法
Navigator.of(context).push(CustomRoute(SecondPage()));
自定義的custom_router
import 'package:flutter/material.dart';
class CustomRoute extends PageRouteBuilder{
final Widget widget;
CustomRoute(this.widget)
:super(
// 設置過度時間
transitionDuration:Duration(seconds: 1),
// 構造器
pageBuilder:(
// 上下文和動畫
BuildContext context,
Animation<double> animaton1,
Animation<double> animaton2,
){
return widget;
},
transitionsBuilder:(
BuildContext context,
Animation<double> animaton1,
Animation<double> animaton2,
Widget child,
){
// 需要什么效果把注釋打開就行了
// 漸變效果
return FadeTransition(
// 從0開始到1
opacity: Tween(begin: 0.0,end: 1.0)
.animate(CurvedAnimation(
// 傳入設置的動畫
parent: animaton1,
// 設置效果,快進漫出 這里有很多內置的效果
curve: Curves.fastOutSlowIn,
)),
child: child,
);
// 縮放動畫效果
// return ScaleTransition(
// scale: Tween(begin: 0.0,end: 1.0).animate(CurvedAnimation(
// parent: animaton1,
// curve: Curves.fastOutSlowIn
// )),
// child: child,
// );
// 旋轉加縮放動畫效果
// return RotationTransition(
// turns: Tween(begin: 0.0,end: 1.0)
// .animate(CurvedAnimation(
// parent: animaton1,
// curve: Curves.fastOutSlowIn,
// )),
// child: ScaleTransition(
// scale: Tween(begin: 0.0,end: 1.0)
// .animate(CurvedAnimation(
// parent: animaton1,
// curve: Curves.fastOutSlowIn
// )),
// child: child,
// ),
// );
// 左右滑動動畫效果
// return SlideTransition(
// position: Tween<Offset>(
// // 設置滑動的 X , Y 軸
// begin: Offset(-1.0, 0.0),
// end: Offset(0.0,0.0)
// ).animate(CurvedAnimation(
// parent: animaton1,
// curve: Curves.fastOutSlowIn
// )),
// child: child,
// );
}
);
}