20、Flutter - 混合开发(一)Flutter调用iOS原生相册功能选图片

混合开发(一)Flutter调用iOS原生相册功能选图片

 

详细代码参见Demo

Demo地址 -> flutter_testdemo7

 

混合开发总共两种
1、Flutter 项目调用原生的某些功能
2、原生项目里面包含 Flutter模块

不建议Flutter 和 原生来回切换,
1、性能损耗
2、内存的泄露
    开启了一个Flutter的页面!开辟了8M的内存空间,但是销毁的时候只销毁了2M,是很占内存的所以不要多开Flutter的页面

Flutter 定义是一个单独的APP
与原生的通讯交互
需要通过通道 channel

 

来看一下代码

choose_picture_page.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ChoosePicture extends StatefulWidget {
  @override
  _ChoosePictureState createState() => _ChoosePictureState();
}
class _ChoosePictureState extends State<ChoosePicture> {
//  与原生通讯的管道
//  channel 擦混一个唯一的标记字符串.类似于通知。原生代码中也通过通道唯一标识来获取这个channel
  MethodChannel _methodChannel = MethodChannel('choose_picture_page');

  File _avataFile;

//  监听原生代码的回调
  @override
  void initState() {
    // TODO: implement initState
    _methodChannel.setMethodCallHandler((call) {
      if (call.method == 'imagePath') {
        //转成字符串 toString 截取第7个字符之后的内容 前面的file://是无用的,需要去掉
        String imagePath = call.arguments.toString().substring(7);
        setState(() {
          print(imagePath);
          _avataFile = File(imagePath);
        });
      }
      return null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          GestureDetector(
            onTap: () {
              print('切换图片');
              _methodChannel.invokeMapMethod('picture');
            },
            child: Container(
              height: 300,
              width: 300,
              decoration: BoxDecoration(
                color: Colors.red,
                borderRadius: BorderRadius.circular(10.0), //设置圆角
                image: DecorationImage(
                  image: _avataFile == null
                      ? AssetImage('images/相机.png')
                      : FileImage(_avataFile),

//                fit: BoxFit.cover
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Flutter 向原生代码发送消息,传递信息

_methodChannel.invokeMapMethod('picture');

查看源码里面有一个method  还有一个可选参数arguments

Future<Map<K, V>> invokeMapMethod<K, V>(String method, [ dynamic arguments ]) async {


运行一下,然后用Xcode 打开项目。在 AppDelegate 实现监听。

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"

@interface AppDelegate ()
@property (nonatomic, strong) FlutterMethodChannel * methodChannel;

@end

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  
    FlutterViewController * vc = (FlutterViewController *)self.window.rootViewController;
    
//    拿到Flutter Channel
    NSLog(@"%@",self.window.rootViewController);
    
//    显示线程
//    这里的name 要和Flutter里面的一模一样不要写错了
    self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"choose_picture_page" binaryMessenger:vc];
    UIImagePickerController * imageVC = [[UIImagePickerController alloc] init];
    imageVC.delegate = self;
    
//    监听Flutter的消息
    [self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
//        这里要判断一下收到的消息
        if ([call.method isEqualToString:@"picture"]) {

            [vc presentViewController:imageVC animated:YES completion:nil];
        }
    }];
    
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

用xcode运行一下项目,然后点击图片。比较卡,但是调用相册成功了

实现选择相册中图片的回调方法,将选中的图片数据传给Flutter

#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info
{
    [picker dismissViewControllerAnimated:YES completion:^{
        NSLog(@"%@",info);
        NSString * imagePath = [NSString stringWithFormat:@"%@",info[@"UIImagePickerControllerImageURL"]];
        [self.methodChannel invokeMethod:@"imagePath" arguments:imagePath];
    }];
}

记得配置一下权限,虽然说调用的时候并不一定会报错,但是iOS有权限要求,还是需要配置一下的。


选中的图片地址是这样的

  UIImagePickerControllerImageURL = "file:///Users/liujilou/Library/Developer/CoreSimulator/Devices/748D45A9-4AA7-486E-AB1A-4F613E542FD7/data/Containers/Data/Application/07535D0A-23F0-4C3A-AD63-C48865628F2E/tmp/C7029656-6EE5-45C0-ADC6-AAB300E3E74B.jpeg";

因为得到的图片地址前面 file://  是不需要的,所以需要截掉前面7位

在Flutter 监听回调的时候

//转成字符串 toString 截取第7个字符之后的内容 前面的file://是无用的,需要去掉
String imagePath = call.arguments.toString().substring(7);

这样就实现,Flutter调用原生代码实现选择图片并回调的功能。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值