使用平台视图在Flutter应用程序中托管原生iOS视图
平台视图允许您在Flutter应用程序中嵌入原生视图,以便您可以从Dart应用变换、剪裁和不透明度到原生视图。
例如,这允许您直接在Flutter应用程序中使用Android和iOS SDK中的原生Google地图。
iOS仅使用混合合成,这意味着原生UIView
附加到视图层次结构。
要在iOS上创建平台视图,请使用以下说明:
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 UiKitView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); }
有关更多信息,请参阅以下内容的API文档: UIKitView
。
平台端
#在平台端,使用Swift或Objective-C:
实现工厂和平台视图。FLNativeViewFactory
创建平台视图,平台视图提供对UIView
的引用。例如,FLNativeView.swift
:
import Flutter
import UIKit
class FLNativeViewFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
return FLNativeView(
frame: frame,
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 FLNativeView: NSObject, FlutterPlatformView {
private var _view: UIView
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
_view = UIView()
super.init()
// iOS视图可以在这里创建
createNativeView(view: _view)
}
func view() -> UIView {
return _view
}
func createNativeView(view _view: UIView){
_view.backgroundColor = UIColor.blue
let nativeLabel = UILabel()
nativeLabel.text = "Native text from iOS"
nativeLabel.textColor = UIColor.white
nativeLabel.textAlignment = .center
nativeLabel.frame = CGRect(x: 0, y: 0, width: 180, height: 48.0)
_view.addSubview(nativeLabel)
}
}
最后,注册平台视图。这可以在应用程序或插件中完成。
对于应用程序注册,修改应用程序的AppDelegate.swift
:
import Flutter
import UIKit
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
guard let pluginRegistrar = self.registrar(forPlugin: "plugin-name") else { return false }
let factory = FLNativeViewFactory(messenger: pluginRegistrar.messenger())
pluginRegistrar.register(
factory,
withId: "<platform-view-type>")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
对于插件注册,修改插件的主文件(例如,FLPlugin.swift
):
import Flutter
import UIKit
class FLPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let factory = FLNativeViewFactory(messenger: registrar.messenger())
registrar.register(factory, withId: "<platform-view-type>")
}
}
在Objective-C中,添加工厂和平台视图的头文件。例如,如FLNativeView.h
所示:
#import <Flutter/Flutter.h>
@interface FLNativeViewFactory : NSObject <FlutterPlatformViewFactory>
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
@end
@interface FLNativeView : NSObject <FlutterPlatformView>
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
- (UIView*)view;
@end
实现工厂和平台视图。FLNativeViewFactory
创建平台视图,平台视图提供对UIView
的引用。例如,FLNativeView.m
:
#import "FLNativeView.h"
@implementation FLNativeViewFactory {
NSObject<FlutterBinaryMessenger>* _messenger;
}
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
self = [super init];
if (self) {
_messenger = messenger;
}
return self;
}
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args {
return [[FLNativeView alloc] initWithFrame:frame
viewIdentifier:viewId
arguments:args
binaryMessenger:_messenger];
}
/// Implementing this method is only necessary when the `arguments` in `createWithFrame` is not `nil`.
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
return [FlutterStandardMessageCodec sharedInstance];
}
@end
@implementation FLNativeView {
UIView *_view;
}
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
if (self = [super init]) {
_view = [[UIView alloc] init];
}
return self;
}
- (UIView*)view {
return _view;
}
@end
最后,注册平台视图。这可以在应用程序或插件中完成。
对于应用程序注册,修改应用程序的AppDelegate.m
:
#import "AppDelegate.h"
#import "FLNativeView.h"
#import "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
NSObject<FlutterPluginRegistrar>* registrar =
[self registrarForPlugin:@"plugin-name"];
FLNativeViewFactory* factory =
[[FLNativeViewFactory alloc] initWithMessenger:registrar.messenger];
[[self registrarForPlugin:@"<plugin-name>"] registerViewFactory:factory
withId:@"<platform-view-type>"];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
对于插件注册,修改主插件文件(例如,FLPlugin.m
):
#import <Flutter/Flutter.h>
#import "FLNativeView.h"
@interface FLPlugin : NSObject<FlutterPlugin>
@end
@implementation FLPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FLNativeViewFactory* factory =
[[FLNativeViewFactory alloc] initWithMessenger:registrar.messenger];
[registrar registerViewFactory:factory withId:@"<platform-view-type>"];
}
@end
有关更多信息,请参阅以下内容的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中的平台视图会带来性能权衡。
对于复杂的情况,可以使用一些技术来减轻性能问题。
例如,您可以在Dart中发生动画时使用占位符纹理。换句话说,如果在渲染平台视图时动画缓慢,则考虑截取原生视图的屏幕截图并将其渲染为纹理。
合成限制
#组合iOS平台视图时存在一些限制。
- 不支持
ShaderMask
和ColorFiltered
widget。 - 支持
BackdropFilter
widget,但对其使用方法有一些限制。有关更多详细信息,请查看iOS平台视图Backdrop Filter模糊设计文档。
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。