Flutter MaterialPageRoute 不会在原生 iOS navigatorViewController 上导航

Posted

技术标签:

【中文标题】Flutter MaterialPageRoute 不会在原生 iOS navigatorViewController 上导航【英文标题】:Flutter MaterialPageRoute doesn't navigate over native iOS navigatorViewController 【发布时间】:2020-09-22 11:02:24 【问题描述】:

我使用 Flutter 部分的 FlutterMethodChannel 调用打开了一个原生故事板 UIViewController。现在我想使用 ios(swift) 部分的方法调用导航到其他小部件/视图。 除了一个之外,方法调用和路由部分没有问题。我通过 iOS 代码中的 invokeMethod 从颤振部分导航的新视图被当前的 iOS 视图覆盖。那是新的颤振导航小部件位于我从颤振方法“await platform.invokeMethod('Printy');”打开的 iOS UIViewController 下。我想浏览当前的 iOS UIViewController。

AppDelegate.swift

@objc class AppDelegate: FlutterAppDelegate 
    var navigationController: UINavigationController?
    var CHANNEL: FlutterMethodChannel?
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool 
        let controller = window.rootViewController as! FlutterViewController
        CHANNEL = FlutterMethodChannel(name: "com.flutter.epic/epic", binaryMessenger: controller as! FlutterBinaryMessenger)
        CHANNEL?.setMethodCallHandler  [unowned self] (methodCall, result) in
            if methodCall.method == "Printy" 
                self.newViewController(result)
            
        

        GeneratedPluginRegistrant.register(with: self)
        
        navigationController = UINavigationController(rootViewController: controller)
        navigationController?.isNavigationBarHidden = true
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    
    
    func newViewController(_ result: @escaping FlutterResult) 
        let storyboard : UIStoryboard? = UIStoryboard.init(name: "Main", bundle: nil);
        let window: UIWindow = ((UIApplication.shared.delegate?.window)!)!
        let paytmTransactionController = storyboard!.instantiateViewController(withIdentifier: "PaytmTransactionController") as! PaytmTransactionController
        paytmTransactionController.result = result
        self.navigationController?.pushViewController(paytmTransactionController, animated: true)
    

PaytmTransactionController.swift

class PaytmTransactionController: UIViewController 
    var result: FlutterResult?
    
    override func viewDidLoad() 
        super.viewDidLoad()

    
    
    @IBAction func close(_ sender: Any) 
        self.navigationController?.popViewController(animated: true)
    
    
    @IBAction func showFlutterView(_ sender: Any) 
        self.navigationController?.popViewController(animated: true)
        (UIApplication.shared.delegate as? AppDelegate)!.CHANNEL!.invokeMethod("didRecieveTranscript", arguments: nil)
    

Flutter -> App.dart

class AppState extends State<App> 
final GlobalKey<NavigatorState> navigatorKey =
    new GlobalKey<NavigatorState>();

@override
void initState() 
  super.initState();

  final channelName = 'com.flutter.epic/epic';
  final methodChannel = MethodChannel(channelName);
  methodChannel.setMethodCallHandler(this._didRecieveTranscript);


Future<void> _didRecieveTranscript(MethodCall call) async 
  final String utterance = call.arguments;
  switch (call.method) 
    case "didRecieveTranscript":
      openMyProject(utterance);
      break;
    case "didRecieveNativeViewFactory":
      didRecieveNativeViewFactory(utterance);
      break;
  


Future<void> didRecieveNativeViewFactory(utterance) async 
  navigatorKey.currentState
      .pushNamed("/project", arguments: ScreenArguments());


Future<void> openMyProject(utterance) async 
  navigatorKey.currentState
      .pushNamed("/project", arguments: ScreenArguments());


@override
Widget build(BuildContext context) 
  // TODO: implement build
  if (this._locale == null) 
    return CircularProgressIndicator();
   else 
    return Provider(
      create: (context) => ApiService.create(),
      child: ZoningProvider(
        child: GlobalProvider(
          child: DashboardProvider(
            child: AuthProvider(
              child: MaterialApp(
                title: GlobalVariable.appTitle,
                theme: ThemeData(
                    //fontFamily: FontClass.defaultRegular,
                    ),
                onGenerateRoute: RouterClass().router,
                navigatorKey: navigatorKey,
                supportedLocales: [
                  Locale('en', 'US'),
                  Locale('zh', 'Chinese'),
                ],
                localizationsDelegates: [
                  AppLocalizations.delegate,
                  GlobalWidgetsLocalizations.delegate,
                  GlobalMaterialLocalizations.delegate,
                ],
                localeResolutionCallback: (locale, supportedLocales) 
                  for (var supportedLocale in supportedLocales) 
                    if (supportedLocale.languageCode == locale.languageCode &&
                        supportedLocale.countryCode == locale.countryCode) 
                      return supportedLocale;
                    
                  
                  return supportedLocales.first;
                ,
                locale: _locale,
              ),
            ),
          ),
        ),
      ),
    );
  

【问题讨论】:

【参考方案1】:

经过两天的探索,我找到了解决方案。很简单,只需调用“SystemNavigator.pop()”从 Flutter 端弹出 iOS 路由即可。

【讨论】:

以上是关于Flutter MaterialPageRoute 不会在原生 iOS navigatorViewController 上导航的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Flutter 中的通知导航到应用程序中的特定 MaterialPageRoute

在 Flutter 中的 MaterialPageRoute 之后尝试 showDialogue 时出现“'context != null': is not true”错误?

Flutter MaterialPageRoute 不会在原生 iOS navigatorViewController 上导航

Flutter:类型 'Future<dynamic>' 不是类型 'Widget' 的子类型 // MaterialPageRoute<dynamic>(null))

flutter页面跳转 Route 使用汇总

Flutter 页面路由过渡动画