【Flutter】PlatformViewの表示
実装手順
- Dart
- PlatFormViewの呼び出し
- kotlin/Swift
- 表示するViewの作成
- 表示するViewのFactoryクラス作成
- Pluginクラスの作成
- Pluginの登録
Dart
PlatFormViewの呼び出し
class PlatformViewWidget extends StatelessWidget { const PlatformViewWidget({required this.text}); final String text; @override Widget build(BuildContext context) { final param = {"text": text}; // Platform側の実装と合わせる final viewType = "com.example.platform_view/plugin"; if (Platform.isAndroid) { return AndroidView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: param; creationParamsCodec: const StandardMessageCodec(), ); } else if (Platform.isIOS) { return UiKitView( viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: param; creationParamsCodec: const StandardMessageCodec(), ); } else { return Container(); } } }
kotlin
表示するViewの作成
class MyAndroidView(context: Context?, messenger: BinaryMessenger, id: Int, creationParams: Map<String, String>): PlatformView { private val view: TextView init { view = TextView(context!!).apply { text = param["text"] } } override fun getView(): View { return view } override fun dispose() {} }
表示するViewのFactoryクラス作成
class MyAndroidtViewFactory(private val messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context?, id: Int, args: Any?): PlatformView { val creationParams = args as Map<String?, Any?>? return MyAndroidView(context, messenger, id, creationParams) } }
Pluginクラスの作成
class MyAndroidViewPlugin: FlutterPlugin { override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { flutterPluginBinding.platformViewRegistry .registerViewFactory( "com.example.platform_view/plugin", // Dart側で指定した文字列を指定 MyAndroidViewFactory(flutterPluginBinding.binaryMessenger) // 作成したFactoryクラスを指定 ) } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {} }
MainActivityでPluginの登録
class MainActivity: FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) flutterEngine.plugins.add(MyAndroidViewPlugin()) } }
Swift
表示するViewの作成
class MyUiKitView: NSObject, FlutterPlatformView { private var _view: UIView init( frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger? ) { _view = UIView() _view.backgroundColor = UIColor.white let label = UILabel() label.text = (arguments as! [String: String])["text"] label.textColor = UIColor.black label.textAlignment = .center label.frame = CGRect(x: 0, y: 0, width: 180, height: 48.0) _view.addSubview(label) super.init() } func view() -> UIView { return _view } }
表示するViewのFactoryクラス作成
class MyUiKitViewFactory: 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 MyUiKitView( frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger) } public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { return FlutterStandardMessageCodec.sharedInstance() } }
Pluginクラスの作成
class MyUiKitViewPlugin { public static func register(with registrar: FlutterPluginRegistrar) { // withIdにDart側で指定した文字列を指定 registrar.register( MyUiKitViewFactory(messenger: registrar.messenger()),withId: "com.example.platform_view/plugin") } }
AppDelegateでPluginの登録
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) // 作成したPluginクラスのregisterを呼び出す // forPluginに表示するNativeViewのクラス名を指定 MyUiKitViewPlugin.register(with: self.registrar(forPlugin: "MyUiKitView")!) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
build.gradle覚書き
Android開発時によく使うライブラリのbuild.gradleの定義 バージョン部分は要更新
projectRoot/build.gradle
dependencies
// navigation safe args classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3'
plugins
app/build.gradle
冒頭
// kapt // Roomで使用 apply plugin: 'kotlin-kapt' // navigation safe args apply plugin: 'androidx.navigation.safeargs.kotlin'
dependencies
// kotlin coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' // ViewModelScope implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' // Room implementation 'androidx.room:room-runtime:2.4.3' implementation 'androidx.room:room-ktx:2.4.3' kapt 'androidx.room:room-compiler:2.4.3' // Jetpack Compose implementation 'androidx.activity:activity-compose:1.6.1' implementation 'androidx.compose.material:material:1.3.1' implementation 'androidx.compose.animation:animation:1.3.2' implementation 'androidx.compose.ui:ui-tooling:1.3.2' implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1' implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.1' // NavigationComponent implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
【Android】DialogFragmentの全画面表示
DialogFragmentを全画面表示し、起動元画面を背景に表示させる
Androidでダイアログを全画面で表示したいときの実装方法
XML
ルートのViewGroupの幅、高さをmatch_parentに設定する
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> (以下省略)
View
表示したいダイアログのonStart()の中で処理を追加
- windowのbackgroudにnullを設定
- windosに対してsetLayoutでMATCH_PARENTを設定
override fun onStart() { super.onStart() // 背景タップでダイアログを閉じない dialog!!.setCancelable(false) // 背景のDrawableをなくす(起動元画面が背景に見える状態) dialog!!.window!!.setBackgroundDrawable(null) // ダイアログのウィンドウサイズをMATCH_PARENTに設定 dialog!!.window!!.setLayout( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) }