Flutter
框架既提供了與原生交互的接口,也支持原生項(xiàng)目嵌入 Flutter
蝗罗。雖然支持桐腌,但是 Flutter
其實(shí)不建議在原生項(xiàng)目中嵌入 Flutter
,因?yàn)?Flutter
需要渲染引擎的支持将饺,會比較重量級,不像嵌入 Web
頁這么輕便痛黎。下面以 Flutter
調(diào)起原生相冊為例予弧,我們介紹一下 Flutter
調(diào)起原生的方式。
自己實(shí)現(xiàn) Flutter 調(diào)起原生相冊
-
Flutter
代碼
MethodChannel _methodChannel = MethodChannel('mine_page/method');
File? _avatarFile;
void initState() {
super.initState();
_methodChannel.setMethodCallHandler((call) {
if (call.method == 'imagePath') {
setState(() {
//獲取圖片本地路徑并進(jìn)行截取
String imagePath = call.arguments.toString().substring(7);
_avatarFile = File(imagePath);
});
}
return Future((){});
});
GestureDetector(
onTap: () {
_methodChannel.invokeMapMethod('picture');
},
child: Container(
width: 70,
height: 70,
// 設(shè)置圓角屬性
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
image: (_avatarFile == null)
? AssetImage('images/ChenXi.JPG') as ImageProvider : FileImage(_avatarFile ?? File('')),
)
),
),
),
-
iOS
代碼實(shí)現(xiàn)
@interface AppDelegate () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
/// methodChannel
@property (nonatomic, strong, nullable) FlutterMethodChannel *methodChannel;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
FlutterViewController *vc = (FlutterViewController *)self.window.rootViewController;
self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"mine_page/method" binaryMessenger:vc];
UIImagePickerController *pickerVc = [[UIImagePickerController alloc] init];
pickerVc.delegate = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
if ([call.method isEqualToString:@"picture"]) {
[vc presentViewController:pickerVc animated:YES completion:nil];
}
}];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
[picker dismissViewControllerAnimated:YES completion:^{
NSString *imagePath = [NSString stringWithFormat:@"%@",info[@"UIImagePickerControllerImageURL"]];
[self.methodChannel invokeMethod:@"imagePath" arguments:imagePath];
}];
}
當(dāng)我們想用 Flutter
調(diào)起原生相冊湖饱,并且更換頭像的話我們需要經(jīng)過以下幾個步驟:
-
Flutter
與原生交互的時候借助一個類MethodChannel
掖蛤,所以Flutter
代碼中首先我們定義了一個變量_methodChannel
,并傳入字符串mine_page/method
井厌,就是一個標(biāo)識 - 為頭像添加點(diǎn)擊實(shí)現(xiàn)蚓庭,并調(diào)用
_methodChannel
的invokeMapMethod
方法,傳入picture
仅仆,picture
就是作為打開相冊的標(biāo)識器赞,可以我們自己隨意定義。 - 同樣在
oc
代碼中我們也要定義一個FlutterMethodChannel
類型的屬性methodChannel
蝇恶,調(diào)用methodChannelWithName
方法創(chuàng)建methodChannel
對象拳魁,傳入的第一個參數(shù)要與Flutter
中的字符保持一致惶桐,第二個參數(shù)我們傳的是window
的根控制器撮弧。 - 實(shí)現(xiàn)
setMethodCallHandler
方法,當(dāng)Flutter
中頭像點(diǎn)擊事件執(zhí)行的時候就會調(diào)用setMethodCallHandler
中的回調(diào)姚糊,這里我們判斷call.method
是否為picture
贿衍。 - 在
block
中調(diào)起UIImagePickerController
,并把pickerVc
的代理設(shè)置為self
救恨。 - 實(shí)現(xiàn)選中圖片的代理方法贸辈,并在代理方法中執(zhí)行
[self.methodChannel invokeMethod:@"imagePath" arguments:imagePath]
,這里imagePath
為圖片的本地路徑肠槽。這里原生也是調(diào)用invokeMethod
方法與Flutter
進(jìn)行通訊擎淤。 - 在
Flutter
代碼中實(shí)現(xiàn)setMethodCallHandler
方法奢啥,當(dāng)?shù)?6 步執(zhí)行完后就會執(zhí)行閉包,在這里可以獲取到圖片的路徑嘴拢,把路徑傳給File
類桩盲,創(chuàng)建變量_avatarFile
。最后調(diào)用setState
方法席吴,刷新頁面赌结。 - 頭像部件中
image
屬性進(jìn)行判斷,當(dāng)_avatarFile
有值的時候就顯示本地相冊選中圖片孝冒,否則就使用默認(rèn)圖片柬姚。
使用三方組件實(shí)現(xiàn)調(diào)起相冊功能
Flutter
官方為我們提供了一個三方組件 image_picker 來實(shí)現(xiàn)調(diào)起相冊的功能,這里我們用 image_picker
來實(shí)現(xiàn)一下庄涡。
// 頭像
GestureDetector(
onTap: () {
_pickImage();
},
void _pickImage() async {
try {
XFile? file = await ImagePicker().pickImage(source: ImageSource.gallery);
setState(() {
_avatarFile = File(file?.path ?? '');
});
}catch (e) {
print(e.toString());
setState(() {
_avatarFile = null;
});
}
}
使用三方組件的話我們只需要實(shí)現(xiàn) _pickImage
方法中的這些代碼就可以實(shí)現(xiàn)相冊選擇的功能量承,而且原生工程不需要改代碼,但是需要注意的是 iOS
原生項(xiàng)目需要配置 info.plist
中的相冊權(quán)限穴店。使用三方庫的好處就是運(yùn)行項(xiàng)目的時候會先執(zhí)行 pod install
宴合,把原生相關(guān)的代碼給下載到工程,三方庫中不光有 dart
代碼迹鹅,而且也有原生相關(guān)的代碼卦洽。