flutter-platform-views

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

flutter-platform-views-and-web-embedding

flutter-platform-views-and-web-embedding

Goal

目标

Guides developers through implementing Flutter Platform Views for Android, iOS, and macOS, as well as embedding Flutter into existing web applications. Assumes the user has a configured Flutter environment and is comfortable with Dart, JavaScript, and the relevant native platform languages (Kotlin, Swift).
指导开发者实现面向Android、iOS、macOS的Flutter Platform Views,以及将Flutter嵌入现有Web应用。本文假设用户已配置好Flutter环境,熟悉Dart、JavaScript以及相关原生平台语言(Kotlin、Swift)。

Instructions

操作指南

1. Determine the Target Platform and Embedding Strategy (Decision Logic)

1. 确定目标平台和嵌入策略(决策逻辑)

Before writing code, you must determine the target platform and the specific embedding strategy required by the user.
STOP AND ASK THE USER: "Which platform are you targeting for native view embedding?
  1. Android (Requires choosing between Hybrid Composition or Texture Layer)
  2. iOS (Hybrid Composition only)
  3. macOS (Hybrid Composition only, gesture support limited)
  4. Web (Requires choosing between Full Page mode or Embedded/Multi-view mode)"
Decision Tree:
  • If Android: Ask the user: "Do you prioritize native Android view fidelity (Hybrid Composition) or Flutter rendering performance (Texture Layer)?"
  • If Web: Ask the user: "Are you taking over the full page, or embedding Flutter into specific HTML elements (Embedded/Multi-view mode)?"
编写代码前,你必须先确定目标平台以及用户所需的具体嵌入策略。
请先询问用户: "你要在哪个平台上实现原生视图嵌入?
  1. Android(需要在混合合成(Hybrid Composition)和纹理层(Texture Layer)之间选择)
  2. iOS(仅支持混合合成(Hybrid Composition))
  3. macOS(仅支持混合合成(Hybrid Composition),手势支持有限)
  4. Web(需要在全页面模式和嵌入/多视图模式之间选择)"
决策树:
  • 如果是Android: 询问用户:"你优先考虑原生Android视图保真度(混合合成 Hybrid Composition)还是Flutter渲染性能(纹理层 Texture Layer)?"
  • 如果是Web: 询问用户:"你需要占用全页面,还是将Flutter嵌入到特定HTML元素中(嵌入/多视图模式)?"

2. Implement Android Platform Views

2. 实现Android Platform Views

Based on the user's choice in Step 1, implement the Dart and Kotlin sides.
Dart Implementation: If the user chose Hybrid Composition (Best fidelity, lower Flutter FPS):
dart
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

Widget buildHybridAndroidView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return PlatformViewLink(
    viewType: viewType,
    surfaceFactory: (context, controller) {
      return AndroidViewSurface(
        controller: controller as AndroidViewController,
        gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
        hitTestBehavior: PlatformViewHitTestBehavior.opaque,
      );
    },
    onCreatePlatformView: (params) {
      return PlatformViewsService.initSurfaceAndroidView(
        id: params.id,
        viewType: viewType,
        layoutDirection: TextDirection.ltr,
        creationParams: creationParams,
        creationParamsCodec: const StandardMessageCodec(),
        onFocus: () {
          params.onFocusChanged(true);
        },
      )
        ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
        ..create();
    },
  );
}
If the user chose Texture Layer (Best Flutter FPS, janky quick scrolling):
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildTextureAndroidView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return AndroidView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Kotlin Implementation (Platform Side): Create the View, the Factory, and register it in the
MainActivity
.
kotlin
package dev.flutter.example

import android.content.Context
import android.graphics.Color
import android.view.View
import android.widget.TextView
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory

// 1. Define the View
internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView {
    private val textView: TextView = TextView(context).apply {
        textSize = 72f
        setBackgroundColor(Color.rgb(255, 255, 255))
        text = "Rendered on a native Android view (id: $id)"
    }
    override fun getView(): View = textView
    override fun dispose() {}
}

// 2. Define the Factory
class NativeViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
        val creationParams = args as Map<String?, Any?>?
        return NativeView(context, viewId, creationParams)
    }
}

// 3. Register in MainActivity
class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        flutterEngine
            .platformViewsController
            .registry
            .registerViewFactory("<platform-view-type>", NativeViewFactory())
    }
}
Validate-and-Fix: If the user is embedding a
SurfaceView
or
SurfaceTexture
, instruct them to manually call
invalidate()
on the view when content changes, as they do not invalidate themselves automatically.
根据用户在第一步的选择,实现Dart和Kotlin端的代码。
Dart实现: 如果用户选择了混合合成(Hybrid Composition)(保真度最优,Flutter FPS更低):
dart
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

Widget buildHybridAndroidView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return PlatformViewLink(
    viewType: viewType,
    surfaceFactory: (context, controller) {
      return AndroidViewSurface(
        controller: controller as AndroidViewController,
        gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
        hitTestBehavior: PlatformViewHitTestBehavior.opaque,
      );
    },
    onCreatePlatformView: (params) {
      return PlatformViewsService.initSurfaceAndroidView(
        id: params.id,
        viewType: viewType,
        layoutDirection: TextDirection.ltr,
        creationParams: creationParams,
        creationParamsCodec: const StandardMessageCodec(),
        onFocus: () {
          params.onFocusChanged(true);
        },
      )
        ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
        ..create();
    },
  );
}
如果用户选择了纹理层(Texture Layer)(Flutter FPS最优,快速滚动时可能卡顿):
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildTextureAndroidView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return AndroidView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Kotlin实现(平台端): 创建View、Factory,并在
MainActivity
中注册。
kotlin
package dev.flutter.example

import android.content.Context
import android.graphics.Color
import android.view.View
import android.widget.TextView
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory

// 1. 定义View
internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView {
    private val textView: TextView = TextView(context).apply {
        textSize = 72f
        setBackgroundColor(Color.rgb(255, 255, 255))
        text = "Rendered on a native Android view (id: $id)"
    }
    override fun getView(): View = textView
    override fun dispose() {}
}

// 2. 定义Factory
class NativeViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
        val creationParams = args as Map<String?, Any?>?
        return NativeView(context, viewId, creationParams)
    }
}

// 3. 在MainActivity中注册
class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        flutterEngine
            .platformViewsController
            .registry
            .registerViewFactory("<platform-view-type>", NativeViewFactory())
    }
}
校验修复: 如果用户要嵌入
SurfaceView
SurfaceTexture
,请告知他们在内容变化时需要手动调用视图的
invalidate()
方法,因为这类组件不会自动触发失效刷新。

3. Implement iOS Platform Views

3. 实现iOS Platform Views

iOS uses Hybrid Composition exclusively.
Dart Implementation:
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildIosView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return UiKitView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Swift Implementation (Platform Side):
swift
import Flutter
import UIKit

// 1. Define the View
class FLNativeView: NSObject, FlutterPlatformView {
    private var _view: UIView

    init(frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
        _view = UIView()
        super.init()
        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)
    }
}

// 2. Define the Factory
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)
    }

    public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
          return FlutterStandardMessageCodec.sharedInstance()
    }
}

// 3. Register in AppDelegate
@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)
    }
}
iOS仅支持混合合成(Hybrid Composition)模式。
Dart实现:
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildIosView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return UiKitView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Swift实现(平台端):
swift
import Flutter
import UIKit

// 1. 定义View
class FLNativeView: NSObject, FlutterPlatformView {
    private var _view: UIView

    init(frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
        _view = UIView()
        super.init()
        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)
    }
}

// 2. 定义Factory
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)
    }

    public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
          return FlutterStandardMessageCodec.sharedInstance()
    }
}

// 3. 在AppDelegate中注册
@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)
    }
}

4. Implement macOS Platform Views

4. 实现macOS Platform Views

macOS uses Hybrid Composition. Note that gesture support is currently limited.
Dart Implementation:
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildMacOsView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return AppKitView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Swift Implementation (Platform Side):
swift
import Cocoa
import FlutterMacOS

// 1. Define the View
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
    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.isEditable = false
    nativeLabel.sizeToFit()
    _view.addSubview(nativeLabel)
  }
}

// 2. Define the Factory
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)
  }
  public func createArgsCodec() -> (FlutterMessageCodec & NSObjectProtocol)? {
    return FlutterStandardMessageCodec.sharedInstance()
  }
}

// 3. Register in MainFlutterWindow.swift
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>")
    super.awakeFromNib()
  }
}
macOS使用混合合成(Hybrid Composition)模式,请注意目前手势支持有限。
Dart实现:
dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Widget buildMacOsView(BuildContext context, String viewType, Map<String, dynamic> creationParams) {
  return AppKitView(
    viewType: viewType,
    layoutDirection: TextDirection.ltr,
    creationParams: creationParams,
    creationParamsCodec: const StandardMessageCodec(),
  );
}
Swift实现(平台端):
swift
import Cocoa
import FlutterMacOS

// 1. 定义View
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
    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.isEditable = false
    nativeLabel.sizeToFit()
    _view.addSubview(nativeLabel)
  }
}

// 2. 定义Factory
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)
  }
  public func createArgsCodec() -> (FlutterMessageCodec & NSObjectProtocol)? {
    return FlutterStandardMessageCodec.sharedInstance()
  }
}

// 3. 在MainFlutterWindow.swift中注册
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>")
    super.awakeFromNib()
  }
}

5. Implement Web Embedding

5. 实现Web嵌入

If the user chose Embedded/Multi-view mode, implement the JS and Dart configurations.
JavaScript Implementation (
flutter_bootstrap.js
or HTML script):
javascript
_flutter.loader.load({
  onEntrypointLoaded: async function onEntrypointLoaded(engineInitializer) {
    let engine = await engineInitializer.initializeEngine({
      multiViewEnabled: true, // Enables embedded mode.
    });
    let app = await engine.runApp();
    
    // Add a view to a specific host element
    let viewId = app.addView({
      hostElement: document.querySelector('#flutter-host-element'),
      initialData: { greeting: 'Hello from JS!' }
    });
  }
});
Dart Implementation (
main.dart
):
Validate-and-Fix: Ensure
runWidget
is used instead of
runApp
.
runApp
will fail with a null
implicitView
error in multi-view mode.
dart
import 'dart:ui' show FlutterView;
import 'package:flutter/widgets.dart';

void main() {
  // MUST use runWidget, not runApp, for multi-view web embedding.
  runWidget(
    MultiViewApp(
      viewBuilder: (BuildContext context) => const MyEmbeddedWidget(),
    ),
  );
}

class MultiViewApp extends StatefulWidget {
  const MultiViewApp({super.key, required this.viewBuilder});
  final WidgetBuilder viewBuilder;

  
  State<MultiViewApp> createState() => _MultiViewAppState();
}

class _MultiViewAppState extends State<MultiViewApp> with WidgetsBindingObserver {
  Map<Object, Widget> _views = <Object, Widget>{};

  
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _updateViews();
  }

  
  void didChangeMetrics() {
    _updateViews();
  }

  void _updateViews() {
    final Map<Object, Widget> newViews = <Object, Widget>{};
    for (final FlutterView view in WidgetsBinding.instance.platformDispatcher.views) {
      final Widget viewWidget = _views[view.viewId] ?? _createViewWidget(view);
      newViews[view.viewId] = viewWidget;
    }
    setState(() {
      _views = newViews;
    });
  }

  Widget _createViewWidget(FlutterView view) {
    return View(
      view: view,
      child: Builder(builder: widget.viewBuilder),
    );
  }

  
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return ViewCollection(views: _views.values.toList(growable: false));
  }
}

class MyEmbeddedWidget extends StatelessWidget {
  const MyEmbeddedWidget({super.key});

  
  Widget build(BuildContext context) {
    // Retrieve the viewId to handle specific logic if needed
    final int viewId = View.of(context).viewId;
    return Directionality(
      textDirection: TextDirection.ltr,
      child: Center(child: Text('Rendered in View ID: $viewId')),
    );
  }
}
如果用户选择了嵌入/多视图模式,请实现JS和Dart端的配置。
JavaScript实现(
flutter_bootstrap.js
或HTML脚本):
javascript
_flutter.loader.load({
  onEntrypointLoaded: async function onEntrypointLoaded(engineInitializer) {
    let engine = await engineInitializer.initializeEngine({
      multiViewEnabled: true, // 启用嵌入模式
    });
    let app = await engine.runApp();
    
    // 将视图添加到指定的宿主元素中
    let viewId = app.addView({
      hostElement: document.querySelector('#flutter-host-element'),
      initialData: { greeting: 'Hello from JS!' }
    });
  }
});
Dart实现(
main.dart
):
校验修复: 确保使用
runWidget
而非
runApp
,在多视图模式下
runApp
会抛出
implicitView
为空的错误。
dart
import 'dart:ui' show FlutterView;
import 'package:flutter/widgets.dart';

void main() {
  // 多视图Web嵌入必须使用runWidget,不能用runApp
  runWidget(
    MultiViewApp(
      viewBuilder: (BuildContext context) => const MyEmbeddedWidget(),
    ),
  );
}

class MultiViewApp extends StatefulWidget {
  const MultiViewApp({super.key, required this.viewBuilder});
  final WidgetBuilder viewBuilder;

  
  State<MultiViewApp> createState() => _MultiViewAppState();
}

class _MultiViewAppState extends State<MultiViewApp> with WidgetsBindingObserver {
  Map<Object, Widget> _views = <Object, Widget>{};

  
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _updateViews();
  }

  
  void didChangeMetrics() {
    _updateViews();
  }

  void _updateViews() {
    final Map<Object, Widget> newViews = <Object, Widget>{};
    for (final FlutterView view in WidgetsBinding.instance.platformDispatcher.views) {
      final Widget viewWidget = _views[view.viewId] ?? _createViewWidget(view);
      newViews[view.viewId] = viewWidget;
    }
    setState(() {
      _views = newViews;
    });
  }

  Widget _createViewWidget(FlutterView view) {
    return View(
      view: view,
      child: Builder(builder: widget.viewBuilder),
    );
  }

  
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return ViewCollection(views: _views.values.toList(growable: false));
  }
}

class MyEmbeddedWidget extends StatelessWidget {
  const MyEmbeddedWidget({super.key});

  
  Widget build(BuildContext context) {
    // 可获取viewId以处理特定业务逻辑
    final int viewId = View.of(context).viewId;
    return Directionality(
      textDirection: TextDirection.ltr,
      child: Center(child: Text('Rendered in View ID: $viewId')),
    );
  }
}

Constraints

限制条件

  • Do not use
    runApp
    when configuring Flutter Web for multi-view embedding. You must use
    runWidget
    and manage the
    FlutterView
    lifecycle via
    WidgetsBindingObserver
    .
  • Do not use
    ShaderMask
    or
    ColorFiltered
    widgets over iOS Platform Views, as they are unsupported.
    BackdropFilter
    has strict limitations.
  • Do not assume Android
    SurfaceView
    or
    SurfaceTexture
    will automatically invalidate when their content changes. You must manually call
    invalidate()
    on the view or its parent.
  • Do not wrap the entire output in a markdown code block. Return raw markdown text.
  • Always verify the Android API level is 23+ before implementing Platform Views.
  • 为Flutter Web配置多视图嵌入时禁止使用
    runApp
    ,必须使用
    runWidget
    并通过
    WidgetsBindingObserver
    管理
    FlutterView
    的生命周期。
  • 禁止在iOS Platform Views上使用
    ShaderMask
    ColorFiltered
    组件,它们不受支持,
    BackdropFilter
    也有严格的使用限制。
  • 不要假设Android的
    SurfaceView
    SurfaceTexture
    在内容变化时会自动失效刷新,你必须手动调用视图或其父视图的
    invalidate()
    方法。
  • 不要将全部输出包裹在Markdown代码块中,返回原始Markdown文本即可。
  • 实现Platform Views前请务必确认Android API等级为23及以上。