集成平台视图 (后称为平台视图) 允许将原生视图嵌入到 Flutter 应用中,所以你可以通过 Dart 将变换、裁剪和不透明度等效果应用到原生视图。

例如,这使你可以通过使用平台视图直接在 Flutter 应用内部使用 Android 和 iOS SDK 中的 Google Maps。

iOS 只支持混合集成模式,这意味着原生的 UIView 会被加入视图层级中。

要在 iOS 中创建平台视图,需要如下步骤:

在 Dart 端

#

在 Dart 端,创建一个 Widget 并添加如下的实现,具体如下:

在 Dart 文件中,例如 native_view_example.dart,请执行下列操作:

  1. 添加如下导入代码:

    dart
    import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart';
  2. 实现 build() 方法:

    dart
    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>{};   return UiKitView(  viewType: viewType,  layoutDirection: TextDirection.ltr,  creationParams: creationParams,  creationParamsCodec: const StandardMessageCodec(),  ); }

更多信息,请查看 API 文档:UIKitView

在平台端

#

在平台端,你可以使用 Swift 或是 Objective-C:

实现工厂和平台视图。 FLNativeViewFactory 创建一个关联了 UIView 的平台视图。举个例子,FLNativeView.swift

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 &#x26; 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 views can be created here  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:

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):

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 举例:

objc
#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 举例:

objc
#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

objc
#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):

objc
#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:

dart
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');  } }

Performance

#

Platform views in Flutter come with performance trade-offs.

For complex cases, there are some techniques that can be used to mitigate performance issues.

For example, you could use a placeholder texture while an animation is happening in Dart. In other words, if an animation is slow while a platform view is rendered, then consider taking a screenshot of the native view and rendering it as a texture.

Composition limitations

#

There are some limitations when composing iOS Platform Views.