美文网首页Flutter
iOS+Flutter--FlutterBoost(二)

iOS+Flutter--FlutterBoost(二)

作者: Red_Wang | 来源:发表于2020-09-08 16:55 被阅读0次

iOS+Flutter--FlutterBoost(一)

上一章介绍了iOS项目如何集成FlutterBoost,这一章介绍使用FlutterBoost管理页面。

一、修改AppDelegate

import UIKit

// 导入Flutter
import Flutter
import flutter_boost

@UIApplicationMain
class AppDelegate: FlutterAppDelegate { //将UIResponder, UIApplicationDelegate替换为FlutterAppDelegate

    // var window: UIWindow?  //去除window声明,因为FlutterAppDelegate中已经声明

    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        self.window = UIWindow(frame: UIScreen.main.bounds)
        let rootViewController = UINavigationController(rootViewController: FirstViewController())
        self.window?.rootViewController = rootViewController
        self.window?.backgroundColor = .white
        self.window?.makeKeyAndVisible()

        let router: FLBPlatform = PlatformRouter()
        FlutterBoostPlugin.sharedInstance().startFlutter(with: router) { (flutterEngine) in
            print("#######  flutterEngine  #########")
        }

        return true
    }
}

二、添加PlatformRouter,代码如下:

import Foundation
import flutter_boost

class PlatformRouter: NSObject, FLBPlatform {
    
    func openNative(_ url: String, urlParams: [AnyHashable : Any],
                    exts: [AnyHashable : Any], animated: Bool,
                    completion: @escaping (Bool) -> Void) {
        
        let prefix = "nativebus://"
        guard url.hasPrefix(prefix) else {
            completion(false)
            return
        }
        
        let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
        let viewControllerName = String(url.dropFirst(prefix.count))
        guard let cls: AnyClass = NSClassFromString(namespace + "." + viewControllerName),
            let clsType = cls as? UIViewController.Type else {
            completion(false)
            return
        }
        let targetViewController = clsType.init()
        targetViewController.urlParams = urlParams
        self.navigationController().pushViewController(targetViewController, animated: animated)
    }
    
    func open(_ url: String, urlParams: [AnyHashable : Any],
              exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        var animated = false
        if exts["animated"] != nil {
            animated = exts["animated"] as! Bool
        }
        
        guard url.hasPrefix("flutterbus://") else {
            //处理 nativebus: 页面
            openNative(url, urlParams: urlParams, exts: exts, animated: animated, completion: completion)
            return
        }
        
        let vc = FLBFlutterViewContainer()
        vc.setName(url, params: urlParams)
        navigationController().pushViewController(vc, animated: animated)
        completion(true)
    }
    
    func present(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any],
                 completion: @escaping (Bool) -> Void) {
        var animated = false
        if exts["animated"] != nil {
            animated = exts["animated"] as! Bool
        }
        let vc = FLBFlutterViewContainer()
        vc.setName(url, params: urlParams)
        navigationController().present(vc, animated: animated) {
            completion(true)
        };
    }
    
    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 = navigationController().presentedViewController
        let vc = presentedVC as? FLBFlutterViewContainer
        if vc?.uniqueIDString() == uid {
            vc?.dismiss(animated: animated, completion: {
                completion(true)
            })
        } else {
            navigationController().popViewController(animated: animated)
        }
    }
    
    func navigationController() -> UINavigationController {
        let delegate = UIApplication.shared.delegate as! AppDelegate
        let navigationController = delegate.window?.rootViewController as! UINavigationController
        return navigationController;
    }
}

Flutter_Boost官方给出了FLBPlatform协议默认实现,具体可查看PlatformRouterImp,PlatformRouter在此基础上加了openNative代码

三、在FlutterBoostDemo module中配置路由页面

import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';

import 'FirstPage.dart';

void main() => runApp(MyApp());

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

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    // 注册Native可以调用的页面
    FlutterBoost.singleton.registerPageBuilders({
      'flutterbus://FirstPage': (pageName, params, _) =>
          FirstPage(params: params),
    });
  }

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

四、Native 打开Flutter页面

通过FlutterBoostPlugin的open方法打开Flutter页面,代码如下

import UIKit
import Foundation
import flutter_boost

class FirstViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "First Page"
        
        let button = UIButton(frame: CGRect(x: 80, y: 100, width: 200, height: 40))
        button.backgroundColor = .red
        button.setTitle("Native打开Fluter页面", for: UIControl.State.normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 13)
        button.setTitleColor(.white, for: UIControl.State.normal)
        button.addTarget(self, action: #selector(openFlutterPage), for: UIControl.Event.touchUpInside)
        view.addSubview(button)
    }
    
    @objc func openFlutterPage() {
        let urlParams = ["startCount": 5] // 传入参数,Flutter可接收
        FlutterBoostPlugin.open("flutterbus://FirstPage", urlParams: urlParams, exts: [:], onPageFinished: { (map) in
           print(map)
        }) { (finished) in
        }
    }
}

五、Flutter打开Native页面

Flutter代码如下:

import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';

class FirstPage extends StatefulWidget {
  FirstPage({
    Key key,
    this.params,
  }) : super(key: key);

  final Map params; //Native传入

  @override
  State<StatefulWidget> createState() {
    _FirstPageState homeState = _FirstPageState();
    homeState.counter = params['startCount'];
    return homeState;
  }
}

class _FirstPageState extends State<FirstPage> {
  int counter;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  void _stopCounter() {
    FlutterBoost.singleton.open("nativebus://SecondViewController",
        urlParams: {"message": "Flutter打开Native页面", "finalCount": counter});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  '当前计数为:',
                ),
                Text(
                  '$counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
            Padding(
              padding: EdgeInsets.all(12),
            ),
            Text(
              '点击下面按钮计数加1',
            ),
            FlatButton(onPressed: _incrementCounter, child: Icon(Icons.add)),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _stopCounter,
        tooltip: 'Stop',
        child: Icon(Icons.stop),
      ),
    );
  }
}

Native页面代码如下:

import UIKit

class SecondViewController: UIViewController {    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Second Page"
        
        var count = 0
        if let params = urlParams as? [String: Any], let counter = params["finalCount"] as? Int {
            count = counter
        }
        
        let label = UILabel(frame: CGRect(x: 80, y: 100, width: 200, height: 40))
        label.text = "最终计数为\(count)"
        label.backgroundColor = .blue
        label.textColor = .white
        view.addSubview(label)
    }
}

其中urlParams是用UIViewController扩展添加的,代码如下:

import UIKit

private struct AssociatedKey {
    static var urlParams = "urlParams"
}

extension UIViewController {
    
    var urlParams: [AnyHashable : Any]? {
        set {
            objc_setAssociatedObject(self,
                                     &AssociatedKey.urlParams,
                                     newValue,
                                     .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            var result: [AnyHashable : Any]?
            if let params = objc_getAssociatedObject(self, &AssociatedKey.urlParams) as? [AnyHashable : Any] {
                result = params
            }
            return result
        }
    }
}

相关文章

  • iOS+Flutter--FlutterBoost(二)

    iOS+Flutter--FlutterBoost(一) 上一章介绍了iOS项目如何集成FlutterBoost,...

  • iOS+Flutter--FlutterBoost(一)

    FlutterBoost链接:https://github.com/alibaba/flutter_boost i...

  • 二(二)

    发什么神经 突然就很想花钱 一边心疼 一边毫不在乎的花 啧 莫名其妙

  • 二,二

    2017.9.11教师节后的周一,第一次走进教室,刚站到讲台两个小可爱送给我两束花,原谅我那时候人还没有认全没有记...

  • 二〇二〇

    本来这篇小结打算年初写的,但是想想后边还有复试就先放一放,结果复试结束后过了两个月才想起要写这篇小结... 时过境...

  • 二金二木二火二土

    今天看完了极简中国史,这本书看了半个多月,因为是八十年前写的书,不是白话文,所以看的特别累。不过从近代前辈的角度去...

  • 说二『似二非二的二』

    说实话原以为他最多似二,生活小节或许专门学着似二,中枢神经应该不至于非二,没想到最近越来越疯狂地绞尽脑汁地朝着二的...

  • 二胎(二)

    今天宝宝三十周了,还有十周你就要出来了,也许会提前,妈妈和家人都很期待。 到了孕晚期,睡觉是个问题,左睡右睡都不对...

  • 二小姐(二)

    我去了李家,那环境好,夫人老爷小姐都很和蔼,我正坐在由木头和瓷做的椅子上,正等待着女管家来接我,我人生地不熟...

  • 二、递归(二)

    一、棋盘分割问题 【每次切完一个棋盘,就是需要舍弃掉一面,只能在一面操作】

网友评论

    本文标题:iOS+Flutter--FlutterBoost(二)

    本文链接:https://www.haomeiwen.com/subject/zjcjektx.html