使用平台視圖在 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) { // 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(), ); }
如需詳細資訊,請參閱 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 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>")
}
}
對於外掛程式註冊,請修改外掛程式的主要檔案 (例如,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) {
// 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 應用程式快速運行,因為此執行緒很少被阻塞。
當使用混合合成渲染平台視圖時,Flutter UI 會繼續從專用的光柵執行緒組合,但平台視圖會在平台執行緒上執行圖形操作。為了光柵化組合的內容,Flutter 會在其光柵執行緒和平台執行緒之間執行同步。因此,在平台執行緒上執行任何緩慢或阻塞的操作都可能對 Flutter 圖形效能產生負面影響。
除非另有說明,否則本網站上的文件反映 Flutter 的最新穩定版本。頁面最後更新時間:2024-07-20。 檢視原始碼 或回報問題。