본문 바로가기

프로그래밍/Flutter

[flutter] Plugin UIView 사용하기

Context

뷰 인스턴스를 저장하기 위한 저장소 클래스

class Context {
   var sampleView: SampleView?
}

 

FlutterPlatformView

UIView를 포함하고 있는 FlutterPlatformView 구성

class SampleView: NSObject, FlutterPlatformView {
   private let id: Int64
   private var uiView: UIView
    
   init(frame: CGRect, viewIdentifier viewId: Int64, arguments arg: Any?, binaryMessenger messenger: FlutterBinaryMessenger?) {
      self.id = viewId
      
      self.uiView = UIView()
      self.uiView.frame = frame
       
      super.init()
   }
    
   func view() -> UIView {
      return uiView
   }
}

 

FlutterPlatformViewFactory

flutter에서 뷰 생성 요청을 받아 뷰를 생성할 factory 구성

class SampleViewFactory: NSObject, FlutterPlatformViewFactory {
   private var context: Context
   private var messenger: FlutterBinaryMessenger
   
   init(context: Context, messenger: FlutterBinaryMessenger) {
      self.context = context
      self.messenger = messenger
      super.init()
   }
   
   func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
      let view = SampleView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger)
      context.sampleView = view
      return view
   }
}

 

factory 등록

기존 플러그인 등록 메쏘드에 factory를 등록

public class SamplePlugin: NSObject, FlutterPlugin {
   public static func register(with registrar: FlutterPluginRegistrar) {
      let instance = SamplePlugin()
      
      // view factory 추가
      let factory = SampleViewFactory(context: instance.context, messenger: registrar.messenger())
      registrar.register(factory, "sample-view")
      
      
      // 메쏘드 채널 등...
      let channel = FlutterMethodChannel(name: "sample.Method", binaryMessenger: registrar.messenger())
      registrar.addMethodCallDelegate(instance, channel: channel)
         .
         .
         .
   }
   
   var context: Context()
   
}

 

UIKitView

Flutter 에서 해당 뷰 표시

   @override
   Widget build(BuildContext context) {
      return MaterialApp(
         home: Scaffold(
            appBar: AppBar(
               title: const Text('UIView 표시 샘플'),
            ),
            body: Center(
               child: showSampleView(),
            ),
         ),
      );
   }
   
   Widget showSampleView() {
      const String viewType = 'sample-view';
      Map<String, dynamic> params = <String, dynamic> { "param": "sample-param" };
      
      return Container(
         width: double.maxFinite,
         height: 300,
         child: UIKitView {
            viewType: viewType,
            layoutDirection: TextDirection.ltr,
            creationParams: params,
            creationParamsCodec: const StandardMessageCodec(),
            onPlatformViewCreated: (int id) async {
               try {
               
                  // 뷰가 생성된 이후 무언가 처리가 필요한 경우
                  var args = <String, String>{ "id": "$id", "arg": "value" };
                  await _samplePlugin.doSomethingForView(args);
                  
               } on PlatformException { 
               
               }
            },
         )
      );
   }
}

뷰의 실제 인스턴스는 네이티브 Context에 저장되어 있으므로, 뷰의 변경이나 특정 기능 호출이 필요할 경우 메쏘드 채널을 통해 사용