1. 程式人生 > >【Flutter 混合開發】嵌入原生View-iOS

【Flutter 混合開發】嵌入原生View-iOS

![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213818619-1774223380.png) > Flutter 混合開發系列 包含如下: > - 嵌入原生View-Android > - **嵌入原生View-iOS** > - 與原生通訊-MethodChannel > - 與原生通訊-BasicMessageChannel > - 與原生通訊-EventChannel > - 新增 Flutter 到 Android Activity > - 新增 Flutter 到 Android Fragment > - 新增 Flutter 到 iOS > > 每個工作日分享一篇,歡迎關注、點贊及轉發。 ### iOS View 建議使用 Xcode 進行開發,在 Android Studio 左側 project tab下選中 ios 目錄下任意一個檔案,右上角會出現 **Open iOS module in Xcode** , ![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213820536-83732165.png) 點選即可開啟,開啟後如下: ![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213821847-1192660487.png) 在**Runner** 目錄下建立 iOS View,此 View 繼承 **FlutterPlatformView** ,返回一個簡單的 **UILabel** : ```dart import Foundation import Flutter class MyFlutterView: NSObject,FlutterPlatformView { let label = UILabel() init(_ frame: CGRect,viewID: Int64,args :Any?,messenger :FlutterBinaryMessenger) { label.text = "我是 iOS View" } func view() -> UIView { return label } } ``` - **getView** :返回iOS View ![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213823179-720270054.png) ### 註冊PlatformView 建立 MyFlutterViewFactory: ```dart import Foundation import Flutter class MyFlutterViewFactory: NSObject,FlutterPlatformViewFactory { var messenger:FlutterBinaryMessenger init(messenger:FlutterBinaryMessenger) { self.messenger = messenger super.init() } func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { return MyFlutterView(frame,viewID: viewId,args: args,messenger: messenger) } func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { return FlutterStandardMessageCodec.sharedInstance() } } ``` 在 **AppDelegate** 中註冊: ```dart import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) let registrar:FlutterPluginRegistrar = self.registrar(forPlugin: "plugins.flutter.io/custom_platform_view_plugin")! let factory = MyFlutterViewFactory(messenger: registrar.messenger()) registrar.register(factory, withId: "plugins.flutter.io/custom_platform_view") return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ``` 記住 **plugins.flutter.io/custom_platform_view** ,這個字串在 Flutter 中需要與其保持一致。 ### 嵌入Flutter 在 Flutter 中呼叫 ```dart class PlatformViewDemo extends StatelessWidget { @override Widget build(BuildContext context) { Widget platformView() { if (defaultTargetPlatform == TargetPlatform.android) { return AndroidView( viewType: 'plugins.flutter.io/custom_platform_view', onPlatformViewCreated: (viewId) { print('viewId:$viewId'); platforms .add(MethodChannel('com.flutter.guide.MyFlutterView_$viewId')); }, creationParams: {'text': 'Flutter傳給AndroidTextView的引數'}, creationParamsCodec: StandardMessageCodec(), ); }else if(defaultTargetPlatform == TargetPlatform.iOS){ return UiKitView( viewType: 'plugins.flutter.io/custom_platform_view', ); } } return Scaffold( appBar: AppBar(), body: Center( child: platformView(), ), ); } } ``` 上面嵌入的是 iOS View,因此通過 **defaultTargetPlatform == TargetPlatform.iOS** 判斷當前平臺載入,在 iOS 上執行效果: ![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213823978-1597673461.png) ### 設定初始化引數 Flutter 端修改如下: ```dart UiKitView( viewType: 'plugins.flutter.io/custom_platform_view', creationParams: {'text': 'Flutter傳給IOSTextView的引數'}, creationParamsCodec: StandardMessageCodec(), ) ``` - **creationParams** :傳遞的引數,外掛可以將此引數傳遞給 AndroidView 的建構函式。 - **creationParamsCodec** :將 creationParams 編碼後再發送給平臺側,它應該與傳遞給建構函式的編解碼器匹配。值的範圍: - StandardMessageCodec - JSONMessageCodec - StringCodec - BinaryCodec 修改 MyFlutterView : ```dart import Foundation import Flutter class MyFlutterView: NSObject,FlutterPlatformView { let label = UILabel() init(_ frame: CGRect,viewID: Int64,args :Any?,messenger :FlutterBinaryMessenger) { super.init() if(args is NSDictionary){ let dict = args as! NSDictionary label.text = dict.value(forKey: "text") as! String } } func view() -> UIView { return label } } ``` 最終效果: ![](https://img2020.cnblogs.com/other/467322/202010/467322-20201018213824661-668681268.png) ### Flutter 向 iOS View 傳送訊息 修改 Flutter 端,建立 **MethodChannel** 用於通訊: ```dart class PlatformViewDemo extends StatefulWidget { @override _PlatformViewDemoState createState() => _PlatformViewDemoState(); } class _PlatformViewDemoState exten