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調用原生代碼實現選擇圖片並回調的功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章