?成熟的App引入Flutter不可避免的會采用Native+Flutter混編的模式進(jìn)行開發(fā),采用混編原生頁面及flutter之間的跳轉(zhuǎn)就會存在一個混合導(dǎo)航棧的管理問題。比如NativeA --> NativeB --> FlutterC--> FlutterD等。原生跳轉(zhuǎn)Flutter頁面需要通過FlutterViewController去承載,啟動Flutter的engine構(gòu)建flutter的環(huán)境完成頁面渲染等工作。
?Flutter頁面之間的跳轉(zhuǎn)自身也有維護(hù)一個導(dǎo)航棧進(jìn)行Flutter頁面跳轉(zhuǎn)管理(頁面跳轉(zhuǎn)官方推薦使用Navigator類去管理的,筆者項目經(jīng)過技術(shù)選型選擇了GetX輕量型框架進(jìn)行路由管理)。那么就存在在2個導(dǎo)航棧,一個是原生的導(dǎo)航棧管理原生頁面和FlutterVC,另外一個是Flutter頁面內(nèi)部的導(dǎo)航棧。
?CaseA:Native 跳轉(zhuǎn)Flutter頁面
UINavigationController * nav = [self topNav];
NSString * route = @"initRouter";
// 初始化一個FlutterViewController,壓入原生導(dǎo)航棧中
FlutterViewController * flutterVC = [[FlutterViewController alloc] initWithProject:self.project initialRoute:route nibName:nil bundle:nil];
[nav pushViewController:flutterVC animated:YES];
?CaseB:Flutter頁面內(nèi)部跳轉(zhuǎn)
Navigator.pushNamed(context, '/b');跳轉(zhuǎn)到下一個頁面
Navigator.pop(context);// 關(guān)閉當(dāng)前Flutter頁面
筆者用的是Getx
Get.to(page);
?CaseC:Flutter頁面返回上一級頁面,這時候存在2種情況,上一級頁面是flutter或者Native頁面。
1.如果上一級頁面是Flutter頁面那么直接推出flutter的當(dāng)前page
2.如果上一級頁面是Native則需要從導(dǎo)航棧里移FlutterViewController。第二種情況需要原生和Flutter之間構(gòu)建一個通道。調(diào)用原生的 [nav popViewControllerAnimated:YES];
FlutterMethodChannel * methodChannel = [FlutterMethodChannel methodChannelWithName:@"com.flutter" binaryMessenger:flutterVC];
[methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
if ([call.method isEqualToString:@"closeFlutterVC"]) {
[self closeFlutterVC];
}
}];
-(void)closeFlutterVC {
[[ self topNav] popViewControllerAnimated:YES];
}
QA:混合導(dǎo)航棧右滑返回頁面跳級怎么處理?(比如NativeA--->FlutterB--->FlutterC,這時右滑的時候會返回到NativeA頁面,B頁面就跳過了)

經(jīng)過分析這是手勢沖突了,如果flutterVC里有多個flutter Page的時候,右滑返回的手勢是交給了原生頁面處理。
解決方案:flutter有一個API,canpop可以判斷當(dāng)前導(dǎo)航棧里是否還有頁面可以pop。
/// Whether the navigator that most tightly encloses the given context can be
/// popped.
Navigator.canPop(BuildContext context);
