上一篇文章介紹了如何集成Flutter_Boost,本篇將詳細(xì)介紹flutter如何與原生進(jìn)行交互。
首先給出文章demo,具體代碼可作參考。
一:flutter_module項(xiàng)目使用FlutterBoost進(jìn)行路由配置
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方法中通過(guò)FlutterBoost為三個(gè)頁(yè)面注冊(cè)了路由,這里注冊(cè)的路由是原生與flutter通用的,這個(gè)后面可以體現(xiàn)。
二:在Flutter頁(yè)面路由中使用FlutterBoost跳轉(zhuǎn)
總結(jié)在Flutter中有以下幾種跳轉(zhuǎn)方式:
1.Flutter=>Flutter(使用Flutter自己的路由)
Navigator.push(context, MaterialPageRoute(builder: (_) => FirstRouteWidget()));
以下三種跳轉(zhuǎn)方式,都是通過(guò)FlutterBoost進(jìn)行跳轉(zhuǎn),使用的是同一個(gè)方法,只是場(chǎng)景有所不同
FlutterBoost.singleton.open( String url,{Map<dynamic,dynamic> urlParams,Map<dynamic,dynamic> exts)
參數(shù)分別為:頁(yè)面名稱,通信傳參,擴(kuò)展參數(shù)。對(duì)應(yīng)相應(yīng)跳轉(zhuǎn)方式使用如下:
2.Flutter=>Flutter(使用原生的navigationController)
例:first頁(yè)面打開(kāi)路由名稱為second頁(yè)面,傳參為{"query": “aaa”},擴(kuò)展參數(shù)中可以添加一些特殊數(shù)據(jù),這里添加了{(lán)"animated": true},在原生中會(huì)解析為帶動(dòng)畫跳轉(zhuǎn)
FlutterBoost.singleton.open( "second",urlParams: {"query": "aaa"}, exts: {"animated": true})
3.Flutter=>原生(push)
例:first頁(yè)面打開(kāi)原生NativeViewController頁(yè)面,拼接native將在原生項(xiàng)目中解析為跳轉(zhuǎn)原生頁(yè)面,拼接push表明跳轉(zhuǎn)方式。
FlutterBoost.singleton.open( "native_push_NativeViewController",urlParams: {"query": "aaa"}, exts: {"animated": true})
4.Flutter=>原生(present)
同上,使用present跳轉(zhuǎn)方式。
FlutterBoost.singleton.open( "native_present_NativeViewController",urlParams: {"query": "aaa"}, exts: {"animated": true})
另外,F(xiàn)lutter關(guān)閉或返回上級(jí)頁(yè)面使用的是close方法,分為兩種
1.關(guān)閉當(dāng)前頁(yè)面
FlutterBoost.singleton.closeCurrent(result: {}, exts: {});
2.通過(guò)id關(guān)閉指定頁(yè)面
FlutterBoost.singleton.close('id', result: {}, exts: {});
三:原生項(xiàng)目中配置路由通信
import Foundation
//實(shí)現(xiàn)FLBPlatform協(xié)議方法,flutter項(xiàng)目和原生項(xiàng)目使用FlutterBoost進(jìn)行的跳轉(zhuǎn)都會(huì)通過(guò)該類進(jìn)行處理
class PlatformRouterImp: NSObject, FLBPlatform {
//處理打開(kāi)原生頁(yè)面邏輯
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端約定跳轉(zhuǎn)原生的url為三段式結(jié)構(gòu)native_method_name
let urlArr = url.components(separatedBy: "_")
if urlArr.count == 3 {
//通過(guò)類名找到相應(yīng)頁(yè)面
let cls : AnyClass? = NSClassFromString("TestWithFlutter." + urlArr[2])
//該項(xiàng)目中的vc都繼承于BaseViewController,加了一個(gè)params用來(lái)接收Flutter傳過(guò)來(lái)的參數(shù),另有方案的話改為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方法會(huì)在這里進(jìn)行處理
func open(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
if url.prefix(6) == "native" {//約定前面字符為native時(shí)跳轉(zhuǎn)原生頁(yè)面
openNative(url, urlParams: urlParams, exts: exts, completion: completion)
} else {//否則打開(kāi)Flutter頁(yè)面
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方法會(huì)在這里進(jìn)行處理,F(xiàn)lutter項(xiàng)目中不分present打開(kāi)方式,都會(huì)走open方法
func present(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
//直接present出的navVC,會(huì)導(dǎo)致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方法會(huì)在這里進(jìn)行處理
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)
}
}
//獲取應(yīng)用的navigationController,用來(lái)進(jìn)行跳轉(zhuǎn)
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進(jìn)行跳轉(zhuǎn)
例:原生跳轉(zhuǎn)Flutter路由名為flutterPage的頁(yè)面
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"));
}