プラットフォーム ビューを使用して Flutter アプリでネイティブ Android ビューをホストする
プラットフォーム ビューを使用すると、Flutter アプリにネイティブ ビューを埋め込むことができます。 ネイティブ ビューに変換、クリップ、不透明度を適用できるようになります。 ダーツから。
これにより、たとえばネイティブの Android SDK からの Google マップ Flutter アプリ内で直接。
Flutter は 2 つのモードをサポートしています。 ハイブリッド構成と仮想ディスプレイ。
どちらを使用するかはユースケースによって異なります。 見てみましょう:
-
ハイブリッド構成ネイティブを追加します
android.view.View
ビュー階層に移動します。 したがって、キーボードの処理とアクセシビリティは、特別な設定をしなくても機能します。 Android 10 より前では、このモードは大幅に機能しなくなる可能性があります。 Flutter UI のフレーム スループット (FPS) を低下させます。 詳しいコンテキストについては、を参照してください。パフォーマンス。 -
仮想ディスプレイレンダリングする
android.view.View
テクスチャへのインスタンス、 そのため、Android アクティビティのビュー階層内には埋め込まれません。 キーボード処理などの特定のプラットフォームの操作 アクセシビリティ機能が動作しない可能性があります。
Android でプラットフォーム ビューを作成するには、 次の手順を使用します。
ダーツ側では
Dart 側で、Widget
次のビルド実装のいずれかを追加します。
ハイブリッド構成
Dart ファイルでは、
例えばnative_view_example.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';
-
を実装します。
build()
方法: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. const Map<String, dynamic> creationParams = <String, dynamic>{}; 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(); }, ); }
詳細については、次の API ドキュメントを参照してください。
PlatformViewLink
AndroidViewSurface
PlatformViewsService
仮想ディスプレイ
Dart ファイルでは、
例えばnative_view_example.dart
、
次の手順を使用してください。
-
次のインポートを追加します。
import 'package:flutter/material.dart'; import 'package:flutter/services.dart';
-
を実装します。
build()
方法: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 AndroidView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); }
詳細については、次の API ドキュメントを参照してください。
AndroidView
ホーム側
プラットフォーム側では標準を使用しますio.flutter.plugin.platform
パッケージ
Java または Kotlin の場合:
ネイティブ コードで次を実装します。
拡張するio.flutter.plugin.platform.PlatformView
への参照を提供するために、android.view.View
(例えば、NativeView.kt
):
package dev.flutter.example
import android.content.Context
import android.graphics.Color
import android.widget.TextView
import io.flutter.plugin.platform.PlatformView
internal class NativeView(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView {
private val textView: TextView
override fun getView(): View {
return textView
}
override fun dispose() {}
init {
textView = TextView(context)
textView.textSize = 72f
textView.setBackgroundColor(Color.rgb(255, 255, 255))
textView.text = "Rendered on a native Android view (id: $id)"
}
}
のインスタンスを作成するファクトリ クラスを作成します。NativeView
以前に作成した
(例えば、NativeViewFactory.kt
):
package dev.flutter.example
import android.content.Context
import android.view.View
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
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)
}
}
最後にプラットフォームビューを登録します。 これはアプリまたはプラグインで実行できます。
アプリの登録については、
アプリのメインアクティビティを変更する
(例えば、MainActivity.kt
):
package dev.flutter.example
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine
.platformViewsController
.registry
.registerViewFactory("<platform-view-type>",
NativeViewFactory())
}
}
プラグインの登録については、
プラグインのメインクラスを変更する
(例えば、PlatformViewPlugin.kt
):
package dev.flutter.plugin.example
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding
class PlatformViewPlugin : FlutterPlugin {
override fun onAttachedToEngine(binding: FlutterPluginBinding) {
binding
.platformViewRegistry
.registerViewFactory("<platform-view-type>", NativeViewFactory())
}
override fun onDetachedFromEngine(binding: FlutterPluginBinding) {}
}
ネイティブ コードで次を実装します。
拡張するio.flutter.plugin.platform.PlatformView
への参照を提供するために、android.view.View
(例えば、NativeView.java
):
package dev.flutter.example;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.platform.PlatformView;
import java.util.Map;
class NativeView implements PlatformView {
@NonNull private final TextView textView;
NativeView(@NonNull Context context, int id, @Nullable Map<String, Object> creationParams) {
textView = new TextView(context);
textView.setTextSize(72);
textView.setBackgroundColor(Color.rgb(255, 255, 255));
textView.setText("Rendered on a native Android view (id: " + id + ")");
}
@NonNull
@Override
public View getView() {
return textView;
}
@Override
public void dispose() {}
}
を作成するファクトリ クラスを作成します。
のインスタンスNativeView
以前に作成した
(例えば、NativeViewFactory.java
):
package dev.flutter.example;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
import java.util.Map;
class NativeViewFactory extends PlatformViewFactory {
NativeViewFactory() {
super(StandardMessageCodec.INSTANCE);
}
@NonNull
@Override
public PlatformView create(@NonNull Context context, int id, @Nullable Object args) {
final Map<String, Object> creationParams = (Map<String, Object>) args;
return new NativeView(context, id, creationParams);
}
}
最後にプラットフォームビューを登録します。 これはアプリまたはプラグインで実行できます。
アプリの登録については、
アプリのメインアクティビティを変更する
(例えば、MainActivity.java
):
package dev.flutter.example;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
flutterEngine
.getPlatformViewsController()
.getRegistry()
.registerViewFactory("<platform-view-type>", new NativeViewFactory());
}
}
プラグインの登録については、
プラグインのメインファイルを変更する
(例えば、PlatformViewPlugin.java
):
package dev.flutter.plugin.example;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
public class PlatformViewPlugin implements FlutterPlugin {
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
binding
.getPlatformViewRegistry()
.registerViewFactory("<platform-view-type>", new NativeViewFactory());
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {}
}
詳細については、次の API ドキュメントを参照してください。
- a89a40b5-d367-4eea-802c-cb8b390ba010
PlatformViewRegistry
PlatformViewFactory
PlatformView
最後に、build.gradle
ファイル
Android SDK の最小バージョンのいずれかを必要とする場合:
android {
defaultConfig {
minSdkVersion 19 // if using hybrid composition
minSdkVersion 20 // if using virtual display.
}
}
パフォーマンス
Flutter のプラットフォーム ビューにはパフォーマンスのトレードオフが伴います。
たとえば、一般的な Flutter アプリでは、Flutter UI は次のように構成されます。 専用のラスター スレッド上で。これにより、Flutter アプリが高速になります。 メインプラットフォームのスレッドがブロックされることはほとんどないためです。
プラットフォーム ビューはハイブリッド構成でレンダリングされますが、 Flutter UI はプラットフォーム スレッドから構成されます。 これは、OS やプラグインのメッセージの処理などの他のタスクと競合します。
Android 10 より前では、ハイブリッド コンポジションは各 Flutter フレームをコピーしていました グラフィックメモリからメインメモリにコピーして戻します GPU テクスチャに。このコピーはフレームごとに行われるため、パフォーマンスは Flutter UI 全体が影響を受ける可能性があります。 Android 10 以降では、 グラフィックス メモリは 1 回だけコピーされます。
一方、仮想ディスプレイは、 各ピクセルをネイティブビューにします 追加の中間グラフィック バッファーを通過する、 これにより、グラフィック メモリと描画パフォーマンスが犠牲になります。
複雑な場合には、いくつかのテクニックがあります。 これらの問題を軽減するために使用できます。
たとえば、プレースホルダー テクスチャを使用できます。 Dart でアニメーションが発生している間。 つまり、アニメーションが遅いときに、 プラットフォームビューがレンダリングされ、 次に、スクリーンショットを撮ることを検討してください。 ネイティブ ビューとそれをテクスチャとしてレンダリングします。
詳細については、以下を参照してください。
TextureLayer
TextureRegistry
FlutterTextureRegistry
FlutterImageView