Flutter插件开发(原生View显示)

该篇文章记录分析,Flutter插件开发中,怎样通过dart调用原生UI,以iOS为例

核心是Flutter.framework中的FlutterPlatformViews.h文件.

其中包括两个协议,源码如下


@protocol FlutterPlatformView <NSObject>
/**
 * Returns a reference to the `UIView` that is wrapped by this `FlutterPlatformView`.
 */
- (UIView*)view;
@end

FLUTTER_EXPORT
@protocol FlutterPlatformViewFactory <NSObject>
/**
 * Create a `FlutterPlatformView`.
 *
 * Implemented by iOS code that expose a `UIView` for embedding in a Flutter app.
 *
 * The implementation of this method should create a new `UIView` and return it.
 *
 * @param frame The rectangle for the newly created `UIView` measued in points.
 * @param viewId A unique identifier for this `UIView`.
 * @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app.
 *   If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart
 *   code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by
 *   `createArgsCodec`.
 */
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
                                   viewIdentifier:(int64_t)viewId
                                        arguments:(id _Nullable)args;

/**
 * Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
 *
 * Only needs to be implemented if `createWithFrame` needs an arguments parameter.
 */
@optional
- (NSObject<FlutterMessageCodec>*)createArgsCodec;
@end

NS_ASSUME_NONNULL_END

#endif  // FLUTTER_FLUTTERPLATFORMVIEWS_H_

可以看到FlutterPlatformView协议要求实现一个名为view的UIView对象.所以天然UIViewController即可.

FlutterPlatformViewFactory协议要求实现一个初始化方法, 返回一个实现了FlutterPlatformView协议的对象.按上面的说法,很明显返回一个UIViewController

- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
                                   viewIdentifier:(int64_t)viewId
                                        arguments:(id _Nullable)args;
                                       

所以综上,flutter中显示原生View,其实就是通过一个实现了FlutterPlatformViewFactory协议的object对象,来返回一个UIViewController对象,该UIViewController对象中的View就是我们要展示在Flutter层的自定义原生View了.

同样通过实现了FlutterPluginRegistrar协议的对象来实现factoryID注册.

该对象便是插件初始化方法
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar中的registrar对象.
所有方法的注册,View的生成都是通过全局的registrar对象来注册.

注册factoryId的核心方法是

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
                     withId:(NSString*)factoryId;

这样通过registrar注册factoryId来实现flutter层和原生层View的绑定.

Flutter层的调用

大概就是这样,其中FactoryID就是在注册factory时的自定义ID了

Widget _view = Platform.isIOS
        ? UiKitView(
            viewType: "FactoryID",
            creationParams: {"name": _name},
            creationParamsCodec: StandardMessageCodec(),
          )
        : AndroidView(
            viewType: "FactoryID",
            creationParams: {"name": _name},
            creationParamsCodec: StandardMessageCodec(),
          );

通过这种方式来将原生中View包成一个flutter层面的widget来使用.如果没有参数, creationParamsCodec可以为null.

可见iOS的View为UiKitView方法,安卓的使用AndroidView ,本文以iOS为主,安卓原理相同,都是通过一个全局的registrar来实现flutter层和原生层的调度.
其中相关文件主要也是PluginRegistry,PlatformView,PlatformViewFactory

import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;

注册方法大概如下

registrar.platformViewRegistry().registerViewFactory("FactoryID",
                new ddViewFactory(new StandardMessageCodec(),_registrar));

其中ddViewFactory大概如下

public class ddViewFactory extends PlatformViewFactory {
    ...
}

标签: flutter, UIView, FlutterPlatformViewFactory, FlutterPlatformView

添加新评论