前言:
前面介绍了 Flutter 内嵌 android 原生组件;Flutter 内嵌原生组件 for android
这里介绍下 Flutter 内嵌 ios 原生组件 ;
ios 相对于 android 要稍微复杂点(多了几个环节),先看效果
其中 Flutter 代码部分基本不用动;我们添加上 ios部分就可以了;
return UiKitView( viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图 onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调 creationParams: <String, String>{ 'initUrl': widget.initUrl }, //给原生传递初始化参数 就是上面定义的初始化参数 // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec] // 如果存在 creationParams,则该值不能为null creationParamsCodec: const StandardMessageCodec(), );
完整的 native_image.dart
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_plugins/native_image_controller.dart'; class NativeImage extends StatefulWidget { final NativeImageController controller; final String initUrl; const NativeImage({Key? key, required this.initUrl, required this.controller}) : super(key: key); @override _NativeImageState createState() => _NativeImageState(); } class _NativeImageState extends State<NativeImage> { static const MethodChannel _channel = MethodChannel('flutter_plugins_native_image'); @override void initState() { // TODO: implement initState super.initState(); // 执行的切换图命令, 参数就是 图片的url widget.controller.addListener(() { // print( // '-----------------------------imageUrl:${widget.controller.imageUrl}'); _channel .invokeListMethod("changeImage", {'url': widget.controller.imageUrl}); }); } @override void dispose() { // TODO: implement dispose super.dispose(); widget.controller.removeListener(() {}); } @override Widget build(BuildContext context) { return Container( color: Colors.grey, width: MediaQuery.of(context).size.width, height: 200, child: _loadNativeView(), ); } Future<void> onPlatformViewCreated(int id) async { // return widget.onCreated( new FlutterPlugins().) print('-----创建成功'); } _loadNativeView() { if (Platform.isAndroid) { return AndroidView( viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图 onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调 creationParams: <String, String>{ 'initUrl': widget.initUrl }, //给原生传递初始化参数 就是上面定义的初始化参数 // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec] // 如果存在 creationParams,则该值不能为null creationParamsCodec: const StandardMessageCodec(), ); } else if (Platform.isIOS) { return UiKitView( viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图(IOS 必须) onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调 creationParams: <String, String>{ 'initUrl': widget.initUrl }, //给原生传递初始化参数 就是上面定义的初始化参数 // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec] // 如果存在 creationParams,则该值不能为null creationParamsCodec: const StandardMessageCodec(), ); } } }
编写 IOS脚本
打开 Flutter 中 IOS 的工程路径 ;
因为 ios工程都是通过 pod 安装依赖的 ; 所有先执行下 pod install
新建 以下四组文件
nativeViewPluginsView
主要用于图片的具体展示
nativeViewPluginsView.h
// // NSObject+NativeViewPlugins.h // Runner // // Created by user on 2022/6/22. // #import <Foundation/Foundation.h> #import <Flutter/Flutter.h> NS_ASSUME_NONNULL_BEGIN @interface NativeViewPlugins :NSObject<FlutterPlugin> + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar; @end NS_ASSUME_NONNULL_END
NativeViewPluginsView.m
// // NSObject+NativeImage.m // Runner // // Created by user on 2022/6/22. // #import "NativeViewPluginsView.h" @implementation NativeViewPluginsView{ int64_t _viewID; UIImageView * _uiImageView; NSString * _imageUrl; } -(instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId argument:(id _Nullable)args binaryMessager:(NSObject<FlutterBinaryMessenger> *)messenger{ if([super init]){ // 不设置大小也是可以的 // if(frame.size.width == 0 ){ // frame = CGRectMake(frame.origin.x, frame.origin.y, [UIScreen mainScreen].bounds.size.width, 250.0); // } _uiImageView = [[UIImageView alloc] initWithFrame:frame]; _uiImageView.backgroundColor = [UIColor yellowColor]; _viewID = viewId; //NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:args]; NSDictionary *dictionary = args; _imageUrl = dictionary[@"initUrl"]; NSLog(@"imageUrl---------------------->%@",dictionary); NSLog(@"messenger---------------------->%@",messenger); [_uiImageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:_imageUrl]]]]; // [imageview setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:annotation.subtitle]]]]; /// 这里的channelName是和Flutter /// 创建MethodChannel时的名字保持一致的,保证一个原生视图有一个平台通道传递消息 FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"flutter_plugins_native_image" binaryMessenger:messenger]; // 处理 Flutter 发送的消息事件 [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { if ([call.method isEqualToString:@"changeImage"]) { NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:call.arguments]; self->_imageUrl = dictionary[@"url"]; NSLog(@"url---------------------->%@",self->_imageUrl); [self->_uiImageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:_imageUrl]]]]; } }]; } return self; } -(nonnull UIView *)view { return _uiImageView; } @end
NativeViewPluginsFactory
主要用来创建或者调用 NativeViewPluginsView
NativeViewPluginsFactory.h
// // NSObject+NativeViewPluginsFactory.h // Runner // // Created by user on 2022/6/22. // #import <Foundation/Foundation.h> #import <Flutter/Flutter.h> NS_ASSUME_NONNULL_BEGIN @interface NativeViewPluginsFactory : NSObject<FlutterPlatformViewFactory> -(instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messager; @end NS_ASSUME_NONNULL_END
NativeViewPluginsFactory.m
// // NSObject+NativeViewPluginsFactory.m // Runner // // Created by user on 2022/6/22. // #import "NativeViewPluginsFactory.h" #import "NativeViewPluginsView.h" @implementation NativeViewPluginsFactory{ NSObject<FlutterBinaryMessenger>* _messenger; } - (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger> *)messager{ self = [super init]; if(self){ _messenger = messager; } return self; } - (NSObject<FlutterMessageCodec>*)createArgsCodec { return [FlutterStandardMessageCodec sharedInstance]; } - (nonnull NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args { // 接收flutter 传来的 图片 初始化参数;以及启动原生UI时候给的参数 NativeViewPluginsView *view = [[NativeViewPluginsView alloc] initWithFrame:frame viewIdentifier:viewId argument:args binaryMessager:_messenger]; return view; } @end
NativeViewPlugins
用于注册原生页面 调用 NativeViewPluginsFactory
NativeViewPlugins.h
// // NSObject+NativeViewPlugins.h // Runner // // Created by user on 2022/6/22. // #import <Foundation/Foundation.h> #import <Flutter/Flutter.h> NS_ASSUME_NONNULL_BEGIN @interface NativeViewPlugins :NSObject<FlutterPlugin> + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar; @end NS_ASSUME_NONNULL_END
NativeViewPlugins.m
// // NSObject+NativeViewPlugins.m // Runner // // Created by user on 2022/6/22. // #import "NativeViewPlugins.h" #import "NativeViewPluginsFactory.h" @implementation NativeViewPlugins + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar{ // 注册插件 // 注册 NaviveViewPluginsFactory [registrar registerViewFactory:[[NativeViewPluginsFactory alloc] initWithMessenger:registrar.messenger] withId:@"imageView"]; } @end
NativeViewRegistrant
主要用于 注册插件 调用 NativeViewPlugins
NativeViewRegistrant.h
// // NativeViewRegistrant.h // Runner // // Created by user on 2022/6/22. // #import <Foundation/Foundation.h> #import <Flutter/Flutter.h> NS_ASSUME_NONNULL_BEGIN @interface NativeViewRegistrant:NSObject + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry; @end NS_ASSUME_NONNULL_END
NativeViewRegistrant.m
// // NSObject+NativeViewRegistrant.m // Runner // // Created by user on 2022/6/22. // #import "NativeViewRegistrant.h" #import <flutter_plugins/FlutterPluginsPlugin.h> #import "NativeViewPlugins.h" @implementation NativeViewRegistrant + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry { [NativeViewPlugins registerWithRegistrar:[registry registrarForPlugin:@"NativeViewPlugins"]]; } @end
AppDelegate
注册自己写的
#import "AppDelegate.h" #import "GeneratedPluginRegistrant.h" #import "NativeViewRegistrant.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; // Override point for customization after application launch. // 注册自己写的nativeView [NativeViewRegistrant registerWithRegistry:self]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end