본문 바로가기

# 02/Flutter

[Flutter] Platform View!! Native View 를 띄워 보아요!

반응형

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

 

GitHub - jiyeonjoy/flutter_platform_view_app

Contribute to jiyeonjoy/flutter_platform_view_app development by creating an account on GitHub.

github.com

 

 

반응형