Flutter平台视图集成插件simple_platform_view的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter平台视图集成插件simple_platform_view的使用

A Flutter插件,用于直接将平台视图集成到Flutter视图层次结构中,旨在提供最佳性能。

设计

为了实现良好的性能,该插件遵循特定的设计方法:

渲染

  • Flutter UI被渲染为单个视图。
  • 保持栅格化任务在栅格线程上。
  • 这种方法比混合合成模式(将Flutter UI渲染为多个视图并将栅格化任务移动到平台线程)提供了更好的性能。
  • 基本上,该插件继续像没有平台视图一样渲染Flutter UI。

平台视图

  • 平台视图将按原生应用程序的方式进行渲染。
  • 创建平台视图后,它将位于Flutter视图之后。
  • 启用平台视图的可见性包括以下步骤:
    • 将FlutterSurfaceView转换为FlutterImageView以支持位置同步。
    • 清除平台视图下方的内容。
  • 需要一种机制将触摸事件从前端视图转发到平台视图。

结果

使用此插件的一些考虑和结果:

  • 自定义引擎是必需的

    • 该插件需要对引擎本身进行修改。因此,在Android上运行时,您需要使用修改后的版本的Flutter(参见[入门指南])。
    • 虽然最好使用官方Flutter版本,但目前还不可能这样做。
    • 自定义框架仓库:[自定义框架仓库链接]
    • 自定义引擎仓库:[自定义引擎仓库链接]
    • 构建脚本:[构建脚本链接]
  • 内容限制:只有绘制在平台视图顶部的内容才会可见,其下方的内容将被清除。

    • 如果平台视图是透明的,则底层小部件的缺失会变得明显。
    • 但是,如果平台视图是不透明的,则无需渲染背景内容。
    • 因此,此模式仅支持不透明的平台视图
  • FlutterImageView限制

    • 该插件使用FlutterImageView来渲染Flutter UI。在Android 10之前,FlutterImageView每帧都会将每个Flutter帧从图形内存复制到主内存,然后再复制回GPU纹理。由于这种复制每帧发生一次,整个Flutter UI的性能可能会受到影响。
    • 从Android 10开始,FlutterImageView使用HardwareBuffer,性能更好。
  • 混合合成组合:将此模式与混合合成模式结合使用可能导致意外行为,因此在同时集成多种合成模式时应谨慎。

  • 视图层次结构:该插件直接修改视图层次结构,这可能会导致与Flutter本身的冲突。

    • 如果您正在使用虚拟显示模式或混合合成纹理层模式且没有问题,则不需要此插件。
    • 如果您正在使用混合合成模式并且遇到性能问题,可以尝试使用此插件。

入门

平台 状态
Android
iOS
主机操作系统支持 状态
MacOS
Windows
Linux

下载自定义引擎

下载自定义Flutter版本 这里

解压下载的 flutter.zip 文件。

首次运行以下命令以下载自定义引擎工件:

$ path_to_custom_version/flutter/bin/flutter doctor

然后使用它就像正常安装Flutter一样:

$ path_to_custom_version/flutter/bin/flutter build apk

对于其他平台上的应用构建,您应该使用 官方Flutter版本

安装

在您的 pubspec.yaml 文件中添加以下依赖项:

dependencies:
  simple_platform_view:

使用

Android:

要使用此插件,只需将 AndroidView 小部件替换为 SimpleAndroidView

import 'package:simple_platform_view/simple_platform_view.dart';

[@override](/user/override)
Widget build(BuildContext context) {
  return SimpleAndroidView(
    viewType: "your_view_type",
    onPlatformViewCreated: (id) {
      // 您的回调
    },
    creationParams: {},
    creationParamsCodec: const StandardMessageCodec(),
  );
}

如果您在ScrollView中使用 SimpleAndroidView,请向您的 MaterialApp 添加以下内容以防止 StretchingOverscrollIndicator 问题:

import 'package:simple_platform_view/simple_platform_view.dart';

[@override](/user/override)
Widget build(BuildContext context) {
  return MaterialApp(
    // 解决StretchingOverscrollIndicator问题
    scrollBehavior: SimplePlatformViewScrollBehavior(),
  );
}

如果您尝试与其他插件一起使用,请克隆它们并替换实现为 SimpleAndroidView。有关更多详细信息,请参阅示例。

iOS:

iOS不受支持

由其他插件使用

插件
simple_google_maps_flutter
simple_webview_flutter

示例代码

以下是 main.dart 的示例代码:

// import 'package:firebase_core/firebase_core.dart';
// import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:simple_platform_view/simple_platform_view.dart';
import 'package:simple_platform_view_example/screen/select_screen.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // await Firebase.initializeApp();
  // FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      // theme: ThemeData(platform: TargetPlatform.iOS),
      home: const SelectScreen(),
      scrollBehavior: SimplePlatformViewScrollBehavior(),
    );
  }
}

更多关于Flutter平台视图集成插件simple_platform_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter平台视图集成插件simple_platform_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,平台视图(Platform Views)允许你嵌入原生的Android和iOS视图到你的Flutter应用中。simple_platform_view 是一个示例插件,用于展示如何在Flutter中集成平台视图。虽然 simple_platform_view 本身可能不是一个真实存在的官方插件,但我们可以基于这个概念编写一个类似的插件来演示其使用。

以下是如何创建一个简单的Flutter插件来集成平台视图的基本步骤,以及相应的代码案例。

1. 创建Flutter插件

首先,你需要创建一个Flutter插件项目。你可以使用以下命令:

flutter create --org com.example --template=plugin simple_platform_view

2. 配置Android平台视图

android/src/main/java/com/example/simple_platform_view/SimplePlatformViewFactory.java 中实现一个 PlatformViewFactory

package com.example.simple_platform_view;

import android.content.Context;
import android.view.View;
import android.widget.TextView;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;

public class SimplePlatformViewFactory extends PlatformViewFactory implements FlutterPlugin, ActivityAware {
    private ActivityPluginBinding activityBinding;

    @Override
    public PlatformView create(Context context, int id, Object args) {
        return new SimplePlatformView(context, activityBinding.getActivity());
    }

    @Override
    public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) {
        // No-op
    }

    @Override
    public void onDetachedFromEngine(FlutterPluginBinding flutterPluginBinding) {
        // No-op
    }

    @Override
    public void onAttachedToActivity(ActivityPluginBinding binding) {
        activityBinding = binding;
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
        activityBinding = null;
    }

    @Override
    public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
        activityBinding = binding;
    }

    @Override
    public void onDetachedFromActivity() {
        activityBinding = null;
    }

    private static class SimplePlatformView implements PlatformView {
        private final View nativeView;

        SimplePlatformView(Context context, android.app.Activity activity) {
            nativeView = new TextView(context);
            ((TextView) nativeView).setText("Hello from Android Native View!");
        }

        @Override
        public View getView() {
            return nativeView;
        }

        @Override
        public void dispose() {
            // Clean up resources here if needed
        }
    }
}

3. 配置iOS平台视图

ios/Classes/SimplePlatformViewFactory.swift 中实现一个 FlutterPlatformViewFactory

import UIKit
import Flutter

public class SimplePlatformViewFactory: NSObject, FlutterPlatformViewFactory {
    public func create(withFrame frame: CGRect,
                       viewIdentifier viewId: Int64,
                       arguments args: Any?) -> FlutterPlatformView {
        return SimplePlatformView(frame: frame, viewId: viewId, arguments: args)
    }
}

class SimplePlatformView: NSObject, FlutterPlatformView {
    private let nativeView: UIView

    init(frame: CGRect, viewId: Int64, arguments: Any?) {
        self.nativeView = UIView(frame: frame)
        let label = UILabel(frame: frame)
        label.text = "Hello from iOS Native View!"
        label.textAlignment = .center
        self.nativeView.addSubview(label)
        
        super.init()
    }

    public func view() -> UIView {
        return nativeView
    }
}

4. 注册插件

android/src/main/kotlin/com/example/simple_platform_view/SimplePlatformViewPlugin.kt 中注册工厂:

package com.example.simple_platform_view

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.platform.PlatformViewRegistry

class SimplePlatformViewPlugin: FlutterPlugin, ActivityAware {
  override fun onAttachedToEngine(binding: FlutterPluginBinding) {
    val registry = binding.platformViewRegistry
    with(registry) {
      registerViewFactory("simple_platform_view", SimplePlatformViewFactory())
    }
  }

  override fun onDetachedFromEngine(binding: FlutterPluginBinding) {
    // No-op
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    // No-op
  }

  override fun onDetachedFromActivityForConfigChanges() {
    // No-op
  }

  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    // No-op
  }

  override fun onDetachedFromActivity() {
    // No-op
  }
}

ios/Classes/SimplePlatformViewPlugin.swift 中注册工厂:

import Flutter

public class SimplePlatformViewPlugin: NSObject, FlutterPlugin {
  public static func register(with registrar: FlutterPluginRegistrar) {
    let channel = FlutterMethodChannel(name: "simple_platform_view", binaryMessenger: registrar.messenger())
    let factory = SimplePlatformViewFactory()
    
    registrar.register(factory, withId: "simple_platform_view")
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    // No-op
  }
}

5. 在Flutter中使用平台视图

在你的Flutter项目中,你可以使用 ui.platformViewRegistry.registerViewFactory 来注册平台视图,并在布局中使用它:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:simple_platform_view/simple_platform_view.dart'; // 假设你已经将插件添加到pubspec.yaml中

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Platform View Example'),
        ),
        body: Center(
          child: PlatformView(
            viewType: 'simple_platform_view',
          ),
        ),
      ),
    );
  }
}

请注意,上述代码是示例性质的,并且假设你已经在 pubspec.yaml 中添加了你的插件依赖。实际使用中,你需要根据具体需求调整代码。

回到顶部