环境:Xcode 16.3、Flutter 3.29.2、Dart 3.7.2。
使用背景:需要在flutter界面中嵌入一个iOS原生控件。
步骤:
1. iOS侧实现:
1.1:PlatformView实现
class FLNativeView: NSObject, FlutterPlatformView {
private var _view: UIView
// flutter侧传入参数
private var arguments: Any?
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
_view = UIView()
super.init()
_view.backgroundColor = UIColor.white
arguments = args
createNativeView(view: _view)
}
func view() -> UIView {
_view
}
func createNativeView(view _view: UIView) {
let testView = UIView() // 创建需要嵌入的视图
constrain(testView) { testView in
testView.edges == testView.superview!.edges
}
}
}
1.2:FlutterPlatformViewFactory实现
public class FLNativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
public init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
public func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
FLNativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger
)
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
FlutterStandardMessageCodec.sharedInstance() // 用于参数编解码
}
}
1.3:FlutterPlugin实现
public class NativeWebViewPlugin: NSObject, FlutterPlugin {
static let viewId = "platform-view-test"
public static func register(with registrar: FlutterPluginRegistrar) {
let factory = FLNativeViewFactory(messenger: registrar.messenger())
registrar.register(factory, withId: NativeWebViewPlugin.viewId) // 唯一标识符
}
}
1.4:注册FlutterPlugin(可使用引擎注册、或在FlutterViewController中注册,具体方式结合flutter集成方式和使用场景,这里采用后者)
在目标flutter控制器(需要嵌入原生组件、且继承自FlutterViewController的控制器)中执行注册方法:
func registrarPlugin() {
if !hasPlugin("NativeWebViewPlugin") {
let registry = registrar(forPlugin: "NativeWebViewPlugin")
registry?.register(
FLNativeViewFactory(messenger: binaryMessenger),
withId: NativeWebViewPlugin.viewId
)
}
}
2. flutter侧实现
UiKitView(
viewType: "platform-view-test",
layoutDirection: TextDirection.ltr,
creationParams: {'key': 'test'},
creationParamsCodec: const StandardMessageCodec(),
);