在 Flutter 应用中通过平台视图嵌入原生 macOS 视图
了解如何在 Flutter 应用中通过平台视图嵌入原生 macOS 视图。
平台视图让你能在 Flutter 应用中嵌入原生视图,从而从 Dart 对原生视图应用变换、裁剪和透明度。
例如,你可以直接在 Flutter 应用中使用原生 Web 视图。
macOS 使用混合合成(Hybrid composition),即原生 NSView 会追加到视图层级中。
要在 macOS 上创建平台视图,请按以下说明操作:
Dart 端
#在 Dart 端,创建一个 widget 并添加 build 实现,如下列步骤所示:
在 Dart widget 文件中,进行与 native_view_example.dart 中类似的修改:
-
Add the following imports:
- 添加以下 import:
dartimport 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -
Implement a
build()method:- 实现
build()方法:
dartWidget build(BuildContext context) { // This is used in the platform side to register the view. const String viewType = '<platform-view-type>'; // Pass parameters to the platform side. final Map<String, dynamic> creationParams = <String, dynamic>{}; return AppKitView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); } - 实现
更多信息请参阅 AppKitView
API 文档。
平台端
#
实现工厂与平台视图。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 views can be created here
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>")
}
}
插件注册:修改插件主文件:
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) {
// This is used in the platform side to register the view.
const String viewType = '<platform-view-type>';
// Pass parameters to the platform side.
final Map<String, dynamic> creationParams = <String, dynamic>{};
switch (defaultTargetPlatform) {
case TargetPlatform.android:
// return widget on Android.
case TargetPlatform.iOS:
// return widget on iOS.
case TargetPlatform.macOS:
// return widget on macOS.
default:
throw UnsupportedError('Unsupported platform view');
}
}
性能
#Flutter 中的平台视图存在性能权衡。
例如,在典型的 Flutter 应用中,Flutter UI 在专用光栅线程上合成,该线程很少阻塞,因此应用能保持较快响应。
使用混合合成渲染平台视图时,Flutter UI 仍由专用光栅线程合成,但平台视图在平台线程上执行图形操作。为光栅化合并内容,Flutter 会在光栅线程与平台线程之间同步;因此平台线程上的缓慢或阻塞操作会影响 Flutter 图形性能。
除非另有说明,本文档之所提及适用于 Flutter 3.44.0 版本。本页面最后更新时间:2026-06-04。查看文档源码 或者 为本页面内容提出建议。