成熟的App引入Flutter不可避免的会采用Native+Flutter混编的模式进行开发,采用混编原生页面及flutter之间的跳转就会存在一个混合导航栈的管理问题。比如NativeA --> NativeB --> FlutterC--> FlutterD等。原生跳转Flutter页面需要通过FlutterViewController去承载,启动Flutter的engine构建flutter的环境完成页面渲染等工作。
Flutter页面之间的跳转自身也有维护一个导航栈进行Flutter页面跳转管理(页面跳转官方推荐使用Navigator
类去管理的,笔者项目经过技术选型选择了GetX
轻量型框架进行路由管理)。那么就存在在2个导航栈,一个是原生的导航栈管理原生页面和FlutterVC,另外一个是Flutter页面内部的导航栈。
CaseA
:Native 跳转Flutter页面
UINavigationController * nav = [self topNav];
NSString * route = @"initRouter";
// 初始化一个FlutterViewController,压入原生导航栈中
FlutterViewController * flutterVC = [[FlutterViewController alloc] initWithProject:self.project initialRoute:route nibName:nil bundle:nil];
[nav pushViewController:flutterVC animated:YES];
CaseB
:Flutter页面内部跳转
Navigator.pushNamed(context, '/b');跳转到下一个页面
Navigator.pop(context);// 关闭当前Flutter页面
笔者用的是Getx
Get.to(page);
CaseC
:Flutter页面返回上一级页面,这时候存在2种情况,上一级页面是flutter或者Native页面。
1.如果上一级页面是Flutter页面那么直接推出flutter的当前page
2.如果上一级页面是Native则需要从导航栈里移FlutterViewController。第二种情况需要原生和Flutter之间构建一个通道。调用原生的 [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:混合导航栈右滑返回页面跳级怎么处理?(比如NativeA--->FlutterB--->FlutterC,这时右滑的时候会返回到NativeA页面,B页面就跳过了)
屏幕录制2022-01-13 下午2.33.19.gif
经过分析这是手势冲突了,如果flutterVC里有多个flutter Page的时候,右滑返回的手势是交给了原生页面处理。
解决方案:flutter有一个API,canpop可以判断当前导航栈里是否还有页面可以pop。
/// Whether the navigator that most tightly encloses the given context can be
/// popped.
Navigator.canPop(BuildContext context);
2022-01-13 19.32.21.gif
网友评论