iOS使用Flutter_Boost管理页面跳转

上一篇文章介绍了如何集成Flutter_Boost,本篇将详细介绍flutter如何与原生进行交互。

首先给出文章demo,具体代码可作参考。

一:flutter_module项目使用FlutterBoost进行路由配置
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'simple_page_widgets.dart';

void main() {
  run App(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    FlutterBoost.singleton.registerPageBuilders({
      'first': (pageName, params, _) => FirstRouteWidget(),
      'second': (pageName, params, _) => SecondRouteWidget(),
      'flutterPage': (pageName, params, _) {
        print("flutterPage params:$params");
        return FlutterRouteWidget(params:params);
      },
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter example',
        builder: FlutterBoost.init(postPush: _onRoutePushed),
        home: Container());
  }

  void _onRoutePushed(
      String pageName, String uniqueId, Map params, Route route, Future _) {
  }
}

这里首先在Widget builder中初始化了FlutterBoost,然后在initState方法中通过FlutterBoost为三个页面注册了路由,这里注册的路由是原生与flutter通用的,这个后面可以体现。

二:在Flutter页面路由中使用FlutterBoost跳转

总结在Flutter中有以下几种跳转方式:
1.Flutter=>Flutter(使用Flutter自己的路由)

Navigator.push(context, MaterialPageRoute(builder: (_) => FirstRouteWidget()));

以下三种跳转方式,都是通过FlutterBoost进行跳转,使用的是同一个方法,只是场景有所不同

FlutterBoost.singleton.open( String url,{Map<dynamic,dynamic> urlParams,Map<dynamic,dynamic> exts)

参数分别为:页面名称,通信传参,扩展参数。对应相应跳转方式使用如下:
2.Flutter=>Flutter(使用原生的navigationController)
例:first页面打开路由名称为second页面,传参为{"query": “aaa”},扩展参数中可以添加一些特殊数据,这里添加了{"animated": true},在原生中会解析为带动画跳转

FlutterBoost.singleton.open( "second",urlParams: {"query": "aaa"}, exts: {"animated": true})

3.Flutter=>原生(push)
例:first页面打开原生NativeViewController页面,拼接native将在原生项目中解析为跳转原生页面,拼接push表明跳转方式。

FlutterBoost.singleton.open( "native_push_NativeViewController",urlParams: {"query": "aaa"}, exts: {"animated": true})

4.Flutter=>原生(present)
同上,使用present跳转方式。

FlutterBoost.singleton.open( "native_present_NativeViewController",urlParams: {"query": "aaa"}, exts: {"animated": true})

另外,Flutter关闭或返回上级页面使用的是close方法,分为两种
1.关闭当前页面

FlutterBoost.singleton.closeCurrent(result: {}, exts: {});

2.通过id关闭指定页面

FlutterBoost.singleton.close('id', result: {}, exts: {});
三:原生项目中配置路由通信
import Foundation

//实现FLBPlatform协议方法,flutter项目和原生项目使用FlutterBoost进行的跳转都会通过该类进行处理
class PlatformRouterImp: NSObject, FLBPlatform {
    //处理打开原生页面逻辑
    func openNative(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        var animated = false
        if exts["animated"] != nil{
            animated = exts["animated"] as! Bool
        }
        //与flutter端约定跳转原生的url为三段式结构native_method_name
        let urlArr = url.components(separatedBy: "_")
        if urlArr.count == 3 {
            //通过类名找到相应页面
            let cls : AnyClass? = NSClassFromString("TestWithFlutter." + urlArr[2])
            //该项目中的vc都继承于BaseViewController,加了一个params用来接收Flutter传过来的参数,另有方案的话改为UIViewController即可。
            if let clsType = cls as? BaseViewController.Type {
                let targetVC = clsType.init()
                targetVC.params = urlParams
                if urlArr[1] == "push" {
                    self.navigationController().pushViewController(targetVC, animated: animated)
                    completion(true)
                } else if urlArr[1] == "present" {
                    let navVC = UINavigationController(rootViewController: targetVC)
                    self.navigationController().present(navVC, animated: animated) {
                        completion(true)
                    }
                }
            }
        }
    }
    //FlutterBoost的open方法会在这里进行处理
    func open(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        if url.prefix(6) == "native" {//约定前面字符为native时跳转原生页面
            openNative(url, urlParams: urlParams, exts: exts, completion: completion)
        } else {//否则打开Flutter页面
            var animated = false
            if exts["animated"] != nil{
                animated = exts["animated"] as! Bool
            }
            let vc = FLBFlutterViewContainer.init()
            vc.setName(url, params: urlParams)
            self.navigationController().pushViewController(vc, animated: animated)
            completion(true)
        }
    }
    //FlutterBoost的present方法会在这里进行处理,Flutter项目中不分present打开方式,都会走open方法
    func present(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        //直接present出的navVC,会导致flutter路由中uniqueid混乱,有待研究
//        var animated = false
//        if exts["animated"] != nil{
//            animated = exts["animated"] as! Bool
//        }
        let vc = FLBFlutterViewContainer.init()
        vc.setName(url, params: urlParams)
        let navVC = UINavigationController(rootViewController: vc)
        navVC.modalPresentationStyle = .fullScreen
        let delegate = UIApplication.shared.delegate as! AppDelegate
        delegate.window?.rootViewController = navVC
//        navigationController().present(navVC, animated: animated) {
//            completion(true)
//        }
    }
    //FlutterBoost的close方法会在这里进行处理
    func close(_ uid: String, result: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        var animated = false;
        if exts["animated"] != nil{
            animated = exts["animated"] as! Bool
        }
        let presentedVC = self.navigationController().presentedViewController
        let vc = presentedVC as? FLBFlutterViewContainer
        if vc?.uniqueIDString() == uid {
            vc?.dismiss(animated: animated, completion: {
                completion(true)
            })
        }else{
            self.navigationController().popViewController(animated: animated)
        }
    }
    //获取应用的navigationController,用来进行跳转
    func navigationController() -> UINavigationController {
        let delegate = UIApplication.shared.delegate as! AppDelegate
        let navigationController = delegate.window?.rootViewController as! UINavigationController
        return navigationController
    }
}
四:在AppDelegate中初始化FlutterBoost
import UIKit
import Flutter

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
    
    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        let router = PlatformRouterImp.init();
        FlutterBoostPlugin.sharedInstance().startFlutter(with: router, onStart: { (engine) in
        });
        
        self.window = UIWindow.init(frame: UIScreen.main.bounds)
        let viewController = ViewController.init()
        let navi = UINavigationController.init(rootViewController: viewController)
        self.window.rootViewController = navi
        self.window.makeKeyAndVisible()
        
        return true
    }
    
}
五:原生使用FlutterBoost进行跳转

例:原生跳转Flutter路由名为flutterPage的页面

        FlutterBoostPlugin.open("flutterPage", urlParams:["query":"aaa"], exts: ["animated":true], onPageFinished: { (_ result:Any?) in
            print(String(format:"call me when page finished, and your result is:%@", result as! CVarArg));
        }) { (f:Bool) in
            print(String(format:"page is opened"));
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容