【Flutter 混合開發】嵌入原生View-iOS
阿新 • • 發佈:2020-10-19
![](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