使用平台视图在 Flutter 应用中托管原生 macOS 视图
平台视图允许您在Flutter应用中嵌入原生视图,以便您可以从Dart应用变换、裁剪和不透明度到原生视图。
例如,这允许您直接在Flutter应用中使用原生网页视图。
macOS使用混合合成,这意味着原生NSView
被附加到视图层次结构中。
要在macOS上创建平台视图,请使用以下说明:
Dart端
#在Dart端,创建一个Widget
并添加构建实现,如下所示。
在Dart widget文件中,进行类似于native_view_example.dart
中所示的更改:
添加以下导入:
dartimport 'package:flutter/foundation.dart'; import 'package:flutter/services.dart';
实现一个
build()
方法:dartWidget build(BuildContext context) { // 这在平台端用于注册视图。 const String viewType = '<platform-view-type>'; // 将参数传递给平台端。 final Map<String, dynamic> creationParams = <String, dynamic>{}; return AppKitView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); }
更多信息,请参见以下API文档:AppKitView
。
平台端
#实现工厂和平台视图。NativeViewFactory
创建平台视图,平台视图提供对NSView
的引用。例如,NativeView.swift
:
import Cocoa
import FlutterMacOS
class NativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(
withViewIdentifier viewId: Int64,
arguments args: Any?
) -> NSView {
return NativeView(
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger)
}
/// Implementing this method is only necessary when the `arguments` in `createWithFrame` is not `nil`.
public func createArgsCodec() -> (FlutterMessageCodec & NSObjectProtocol)? {
return FlutterStandardMessageCodec.sharedInstance()
}
}
class NativeView: NSView {
init(
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
super.init(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
wantsLayer = true
layer?.backgroundColor = NSColor.systemBlue.cgColor
// macOS 视图可以在这里创建
createNativeView(view: self)
}
required init?(coder nsCoder: NSCoder) {
super.init(coder: nsCoder)
}
func createNativeView(view _view: NSView) {
let nativeLabel = NSTextField()
nativeLabel.frame = CGRect(x: 0, y: 0, width: 180, height: 48.0)
nativeLabel.stringValue = "Native text from macOS"
nativeLabel.textColor = NSColor.black
nativeLabel.font = NSFont.systemFont(ofSize: 14)
nativeLabel.isBezeled = false
nativeLabel.focusRingType = .none
nativeLabel.isEditable = true
nativeLabel.sizeToFit()
_view.addSubview(nativeLabel)
}
}
最后,注册平台视图。这可以在应用程序或插件中完成。
对于应用程序注册,修改应用程序的MainFlutterWindow.swift
:
import Cocoa
import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
// ...
let registrar = flutterViewController.registrar(forPlugin: "plugin-name")
let factory = NativeViewFactory(messenger: registrar.messenger)
registrar.register(
factory,
withId: "<platform-view-type>")
}
}
对于插件注册,修改插件的主文件(例如,Plugin.swift
):
import Cocoa
import FlutterMacOS
public class Plugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let factory = NativeViewFactory(messenger: registrar.messenger)
registrar.register(factory, withId: "<platform-view-type>")
}
}
更多信息,请参见以下API文档:
整合
#在Dart中实现build()
方法时,您可以使用defaultTargetPlatform
来检测平台,并决定使用哪个widget:
Widget build(BuildContext context) {
// 这在平台端用于注册视图。
const String viewType = '<platform-view-type>';
// 将参数传递给平台端。
final Map<String, dynamic> creationParams = <String, dynamic>{};
switch (defaultTargetPlatform) {
case TargetPlatform.android:
// 在Android上返回widget。
case TargetPlatform.iOS:
// 在iOS上返回widget。
case TargetPlatform.macOS:
// 在macOS上返回widget。
default:
throw UnsupportedError('不支持的平台视图');
}
}
性能
#Flutter中的平台视图存在性能权衡。
例如,在一个典型的Flutter应用程序中,Flutter UI是在一个专用的光栅线程上组成的。这使得Flutter应用程序运行速度很快,因为此线程很少被阻塞。
当使用混合合成渲染平台视图时,Flutter UI继续从专用的光栅线程组成,但平台视图在平台线程上执行图形操作。为了光栅化组合的内容,Flutter在其光栅线程和平台线程之间执行同步。因此,平台线程上的任何缓慢或阻塞操作都会对Flutter图形性能产生负面影响。
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。