반응형
flutter 로 개발을 하다보면 네이티브 뷰를 띄워야 되는 경우가 종종 있는데
예를 들어! 어떤 sdk 를 붙이고 싶은데 네이티브만 지원하는 경우..
이럴 때는 어쩔 수 없이 네이티브를 각각 구현 한 다음 뷰를 붙여주는 작업이 필요하다!
먼저 플러터쪽 코드!
import 'dart:io';
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';
// ignore_for_file: constant_identifier_names
class PlatformWidget extends StatelessWidget {
static const String PLUGIN_VIEW_TYPE = "plugin/native_widget";
const PlatformWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
if (Platform.isAndroid) {
Map<String, dynamic> creationParams = <String, dynamic>{
'key': 'message',
};
return PlatformViewLink(
viewType: PLUGIN_VIEW_TYPE,
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: PLUGIN_VIEW_TYPE,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
onFocus: () {
params.onFocusChanged(true);
},
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
},
);
} else {
Map<String, dynamic> creationParams = <String, dynamic>{
'key': 'message',
};
return UiKitView(
viewType: PLUGIN_VIEW_TYPE,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
}
}
안드로이드와 iOS 각각 다른 위젯을 호출해 줘야되고
creationParams
을 통해 데이터를 넘겨 줄 수도 있다!!
안드로이드 코드!
package com.example.flutter_platform_view_app
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
flutterEngine
.platformViewsController
.registry
.registerViewFactory("plugin/native_widget", NativeViewFactory())
}
}
package com.example.flutter_platform_view_app
import android.content.Context
import android.graphics.Color
import android.view.View
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 = TextView(context)
override fun getView(): View {
return textView
}
override fun dispose() {}
init {
val message: String = creationParams?.get("key").toString()
textView.textSize = 30f
textView.setBackgroundColor(Color.rgb(255, 255, 255))
textView.text = "Rendered on a native Android view (message: $message)"
}
}
package com.example.flutter_platform_view_app
import android.content.Context
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)
}
}
안드로이드에서 구현해준 뷰가 잘 뜨는 것을 확인 할 수 있다!!
다음 iOS 코드!!
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
weak var nativeRegistrar = self.registrar(forPlugin: "NativeViewPlugin")
let nativeFactory = NativeViewFactory(messenger: nativeRegistrar!.messenger())
self.registrar(forPlugin: "<NativeViewPlugin>")!.register(
nativeFactory,
withId: "plugin/native_widget")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
import Flutter
import UIKit
class NativeViewFactory: 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 NativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger)
}
}
class NativeView: 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)
}
}
import Flutter
import UIKit
class NativeViewPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let nativeViewFactory = NativeViewFactory(messenger: registrar.messenger())
registrar.register(nativeViewFactory, withId: "plugin/native_widget")
}
}
iOS 에서 구현해 준 뷰도 잘 뜨는 것을 확인할 수 있다!!!!
전체 코드는 여기서 확인할 수 있다.
https://github.com/jiyeonjoy/flutter_platform_view_app
반응형
'# 02 > Flutter' 카테고리의 다른 글
[Flutter] iOS UiKitView 구현 시 실선 노출 !! (0) | 2022.12.22 |
---|---|
[Flutter] iOS 카메라 비디오 녹화 시 간헐적으로 블랙 프레임 생기는 현상 (0) | 2022.12.05 |
[Flutter] WillPopScope 사용 시 iOS swipe 안돼요! (0) | 2022.11.10 |
[Flutter] Image File Size ????? (1) | 2022.11.10 |
[Flutter] LG 폰 Camera Flash 안꺼져요.. (0) | 2022.10.27 |