• Flutter 内嵌原生组件 for ios


    前言:

    前面介绍了 Flutter 内嵌 android 原生组件;Flutter 内嵌原生组件 for android

    这里介绍下 Flutter 内嵌 ios 原生组件  ;

    ios 相对于 android 要稍微复杂点(多了几个环节),先看效果

    其中 Flutter 代码部分基本不用动;我们添加上 ios部分就可以了; 

    1. return UiKitView(
    2. viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图
    3. onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调
    4. creationParams: <String, String>{
    5. 'initUrl': widget.initUrl
    6. }, //给原生传递初始化参数 就是上面定义的初始化参数
    7. // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec]
    8. // 如果存在 creationParams,则该值不能为null
    9. creationParamsCodec: const StandardMessageCodec(),
    10. );

    完整的 native_image.dart

    1. import 'dart:io';
    2. import 'package:flutter/material.dart';
    3. import 'package:flutter/services.dart';
    4. import 'package:flutter_plugins/native_image_controller.dart';
    5. class NativeImage extends StatefulWidget {
    6. final NativeImageController controller;
    7. final String initUrl;
    8. const NativeImage({Key? key, required this.initUrl, required this.controller})
    9. : super(key: key);
    10. @override
    11. _NativeImageState createState() => _NativeImageState();
    12. }
    13. class _NativeImageState extends State<NativeImage> {
    14. static const MethodChannel _channel =
    15. MethodChannel('flutter_plugins_native_image');
    16. @override
    17. void initState() {
    18. // TODO: implement initState
    19. super.initState();
    20. // 执行的切换图命令, 参数就是 图片的url
    21. widget.controller.addListener(() {
    22. // print(
    23. // '-----------------------------imageUrl:${widget.controller.imageUrl}');
    24. _channel
    25. .invokeListMethod("changeImage", {'url': widget.controller.imageUrl});
    26. });
    27. }
    28. @override
    29. void dispose() {
    30. // TODO: implement dispose
    31. super.dispose();
    32. widget.controller.removeListener(() {});
    33. }
    34. @override
    35. Widget build(BuildContext context) {
    36. return Container(
    37. color: Colors.grey,
    38. width: MediaQuery.of(context).size.width,
    39. height: 200,
    40. child: _loadNativeView(),
    41. );
    42. }
    43. Future<void> onPlatformViewCreated(int id) async {
    44. // return widget.onCreated( new FlutterPlugins().)
    45. print('-----创建成功');
    46. }
    47. _loadNativeView() {
    48. if (Platform.isAndroid) {
    49. return AndroidView(
    50. viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图
    51. onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调
    52. creationParams: <String, String>{
    53. 'initUrl': widget.initUrl
    54. }, //给原生传递初始化参数 就是上面定义的初始化参数
    55. // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec]
    56. // 如果存在 creationParams,则该值不能为null
    57. creationParamsCodec: const StandardMessageCodec(),
    58. );
    59. } else if (Platform.isIOS) {
    60. return UiKitView(
    61. viewType: 'imageView', //视图标识符 要和原生 保持一致 要不然加载不到视图(IOS 必须)
    62. onPlatformViewCreated: onPlatformViewCreated, //原生视图创建成功的回调
    63. creationParams: <String, String>{
    64. 'initUrl': widget.initUrl
    65. }, //给原生传递初始化参数 就是上面定义的初始化参数
    66. // 用来编码 creationParams 的形式,可选 [StandardMessageCodec], [JSONMessageCodec], [StringCodec], or [BinaryCodec]
    67. // 如果存在 creationParams,则该值不能为null
    68. creationParamsCodec: const StandardMessageCodec(),
    69. );
    70. }
    71. }
    72. }

    编写 IOS脚本

    打开 Flutter 中 IOS 的工程路径 ;

    因为 ios工程都是通过   pod 安装依赖的 ;  所有先执行下    pod install

     

    新建 以下四组文件

    nativeViewPluginsView 

    主要用于图片的具体展示

    nativeViewPluginsView.h

    1. //
    2. // NSObject+NativeViewPlugins.h
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import <Foundation/Foundation.h>
    8. #import <Flutter/Flutter.h>
    9. NS_ASSUME_NONNULL_BEGIN
    10. @interface NativeViewPlugins :NSObject<FlutterPlugin>
    11. + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar;
    12. @end
    13. NS_ASSUME_NONNULL_END

    NativeViewPluginsView.m

     

    1. //
    2. // NSObject+NativeImage.m
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import "NativeViewPluginsView.h"
    8. @implementation NativeViewPluginsView{
    9. int64_t _viewID;
    10. UIImageView * _uiImageView;
    11. NSString * _imageUrl;
    12. }
    13. -(instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId argument:(id _Nullable)args binaryMessager:(NSObject<FlutterBinaryMessenger> *)messenger{
    14. if([super init]){
    15. // 不设置大小也是可以的
    16. // if(frame.size.width == 0 ){
    17. // frame = CGRectMake(frame.origin.x, frame.origin.y, [UIScreen mainScreen].bounds.size.width, 250.0);
    18. // }
    19. _uiImageView = [[UIImageView alloc] initWithFrame:frame];
    20. _uiImageView.backgroundColor = [UIColor yellowColor];
    21. _viewID = viewId;
    22. //NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:args];
    23. NSDictionary *dictionary = args;
    24. _imageUrl = dictionary[@"initUrl"];
    25. NSLog(@"imageUrl---------------------->%@",dictionary);
    26. NSLog(@"messenger---------------------->%@",messenger);
    27. [_uiImageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:_imageUrl]]]];
    28. // [imageview setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:annotation.subtitle]]]];
    29. /// 这里的channelName是和Flutter
    30. /// 创建MethodChannel时的名字保持一致的,保证一个原生视图有一个平台通道传递消息
    31. FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"flutter_plugins_native_image" binaryMessenger:messenger];
    32. // 处理 Flutter 发送的消息事件
    33. [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
    34. if ([call.method isEqualToString:@"changeImage"]) {
    35. NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:call.arguments];
    36. self->_imageUrl = dictionary[@"url"];
    37. NSLog(@"url---------------------->%@",self->_imageUrl);
    38. [self->_uiImageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:_imageUrl]]]];
    39. }
    40. }];
    41. }
    42. return self;
    43. }
    44. -(nonnull UIView *)view {
    45. return _uiImageView;
    46. }
    47. @end

    NativeViewPluginsFactory

    主要用来创建或者调用 NativeViewPluginsView

    NativeViewPluginsFactory.h  

    1. //
    2. // NSObject+NativeViewPluginsFactory.h
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import <Foundation/Foundation.h>
    8. #import <Flutter/Flutter.h>
    9. NS_ASSUME_NONNULL_BEGIN
    10. @interface NativeViewPluginsFactory : NSObject<FlutterPlatformViewFactory>
    11. -(instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messager;
    12. @end
    13. NS_ASSUME_NONNULL_END

     NativeViewPluginsFactory.m

    1. //
    2. // NSObject+NativeViewPluginsFactory.m
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import "NativeViewPluginsFactory.h"
    8. #import "NativeViewPluginsView.h"
    9. @implementation NativeViewPluginsFactory{
    10. NSObject<FlutterBinaryMessenger>* _messenger;
    11. }
    12. - (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger> *)messager{
    13. self = [super init];
    14. if(self){
    15. _messenger = messager;
    16. }
    17. return self;
    18. }
    19. - (NSObject<FlutterMessageCodec>*)createArgsCodec {
    20. return [FlutterStandardMessageCodec sharedInstance];
    21. }
    22. - (nonnull NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args {
    23. // 接收flutter 传来的 图片 初始化参数;以及启动原生UI时候给的参数
    24. NativeViewPluginsView *view = [[NativeViewPluginsView alloc] initWithFrame:frame viewIdentifier:viewId argument:args binaryMessager:_messenger];
    25. return view;
    26. }
    27. @end

     

    NativeViewPlugins

    用于注册原生页面  调用   NativeViewPluginsFactory

    NativeViewPlugins.h 

    1. //
    2. // NSObject+NativeViewPlugins.h
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import <Foundation/Foundation.h>
    8. #import <Flutter/Flutter.h>
    9. NS_ASSUME_NONNULL_BEGIN
    10. @interface NativeViewPlugins :NSObject<FlutterPlugin>
    11. + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar;
    12. @end
    13. NS_ASSUME_NONNULL_END

     NativeViewPlugins.m

    1. //
    2. // NSObject+NativeViewPlugins.m
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import "NativeViewPlugins.h"
    8. #import "NativeViewPluginsFactory.h"
    9. @implementation NativeViewPlugins
    10. + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar{
    11. // 注册插件
    12. // 注册 NaviveViewPluginsFactory
    13. [registrar registerViewFactory:[[NativeViewPluginsFactory alloc] initWithMessenger:registrar.messenger] withId:@"imageView"];
    14. }
    15. @end

    NativeViewRegistrant

     主要用于 注册插件  调用 NativeViewPlugins

    NativeViewRegistrant.h

    1. //
    2. // NativeViewRegistrant.h
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import <Foundation/Foundation.h>
    8. #import <Flutter/Flutter.h>
    9. NS_ASSUME_NONNULL_BEGIN
    10. @interface NativeViewRegistrant:NSObject
    11. + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
    12. @end
    13. NS_ASSUME_NONNULL_END

     NativeViewRegistrant.m

    1. //
    2. // NSObject+NativeViewRegistrant.m
    3. // Runner
    4. //
    5. // Created by user on 2022/6/22.
    6. //
    7. #import "NativeViewRegistrant.h"
    8. #import <flutter_plugins/FlutterPluginsPlugin.h>
    9. #import "NativeViewPlugins.h"
    10. @implementation NativeViewRegistrant
    11. + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
    12. [NativeViewPlugins registerWithRegistrar:[registry registrarForPlugin:@"NativeViewPlugins"]];
    13. }
    14. @end

    AppDelegate

    注册自己写的

    1. #import "AppDelegate.h"
    2. #import "GeneratedPluginRegistrant.h"
    3. #import "NativeViewRegistrant.h"
    4. @implementation AppDelegate
    5. - (BOOL)application:(UIApplication *)application
    6. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    7. [GeneratedPluginRegistrant registerWithRegistry:self];
    8. // Override point for customization after application launch.
    9. // 注册自己写的nativeView
    10. [NativeViewRegistrant registerWithRegistry:self];
    11. return [super application:application didFinishLaunchingWithOptions:launchOptions];
    12. }
    13. @end
  • 相关阅读:
    Python21天学习挑战赛Day(9)·操作MongoDB数据库
    Ps:明度直方图
    正则表达式
    Paxos 算法详解
    总结最近遇到的几个问题
    【数字信号调制】基于matlab GUI PCM编码和QAM调制系统【含Matlab源码 2080期】
    保姆级教程:Linux (Ubuntu) 部署流光卡片开源 API
    接口使用的最佳时机
    开源啦!一键部署免费使用!Kubernetes上直接运行大数据平台!
    如何在云服务器上部署 Servlet 项目
  • 原文地址:https://blog.csdn.net/nicepainkiller/article/details/125420308