「这是我参与2022初次更文应战的第1天,活动详情检查:2022初次更文应战」
混合开发的方法
提到混合开发,咱们知道无非是两种:
Flutter调用原生
咱们用之前的微信Demo的个人中心头像来做示例,点击头像的时分,唤醒原生的相册。
GestureDetector(
onTap: () {
print('需求引发原生的相机');
_methodChannel.invokeMapMethod('takePhotos');
},
child: Container(
width: 70,
height: 70,
decoration: BoxDecoration(
image:
DecorationImage(image: AssetImage('images/游戏2.png')),
borderRadius: BorderRadius.circular(10)),
),
),
在Flutter和iOS中通讯供给了一个专门的类MethodChannel
用来通信
MethodChannel _methodChannel = MethodChannel('mine/method');
在onTap
的时分调用_methodChannel.invokeMapMethod('takePhotos');
告诉iOS原生我向你发起了一个takePhotos
的办法,iOS你在接收到这个标识的时分要给我调起你自己的相机哦~
此刻咱们来到iOS的项目中:
- 首要示例化
FlutterMethodChannel
这个类,该类的第一个参数是指明哪个途径下的办法 - 调用
setMethodCallHandler
来呼应Flutter发出来的讯息 - 辨认当时的办法针对处理
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var pickVc = UIImagePickerController()
var flutterChannel: FlutterMethodChannel!
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let vc = self.window.rootViewController as? FlutterViewController
pickVc.delegate = self
// 在iOS端也初始话这个通讯的类
flutterChannel = FlutterMethodChannel.init(name: "mine/method", binaryMessenger: vc as! FlutterBinaryMessenger)
// 对Flutter端发过来的通讯处理
flutterChannel.setMethodCallHandler { call, result in
// 如果我辨认了这个办法是`takePhotos` 我就引发原生相机
if call.method.isEqual("takePhotos"){
print("办法来了");
self.pickVc.delegate = self
vc?.present(self.pickVc, animated: true, completion: nil)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
- 当然啦,在iOS中选中了照片,把照片中的信息再回传给Flutter中,调用
invokeMethod
回传
extension AppDelegate: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let imagePathURL = info[UIImagePickerController.InfoKey.imageURL] as? NSURL,
let imagePath = imagePathURL.absoluteString {
self.flutterChannel.invokeMethod("editedImage", arguments: imagePath)
}
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
5.Flutter中收到iOS原生端挑选的图片之后,也呼应setMethodCallHandler
@override
void initState() {
// TODO: implement initState
super.initState();
_methodChannel.setMethodCallHandler((call) {
if (call.method == 'editedImage') {
print(call.arguments);
}
return call.arguments;
});
}
至此,两头的通讯现已完成了,咱们能够运用拿到的照片途径替换当时的图片了。
@override
void initState() {
// TODO: implement initState
super.initState();
_methodChannel.setMethodCallHandler((call) {
if (call.method == 'editedImage') {
print(call.arguments);
setState(() {
String subString = call.arguments.toString().substring(7);
_avatarFile = File(subString);
});
}
return call.arguments;
});
}
BoxDecoration(
image: DecorationImage(
image: _avatarFile == null
? AssetImage('images/游戏2.png') as ImageProvider
: FileImage(_avatarFile!),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(10)
)
image_picker
还有一种运用pub
的方法唤醒相机,这儿运用到了Flutter官方出品的一个库image_picker
咱们安装之后能够参考一下用法,本文的运用还是比较简单的
void _pickerImage() async {
try {
XFile? file = await _picker.pickImage(source: ImageSource.gallery);
if (file != null && mounted) {
setState(() {
_avatarFile = File(file.path);
});
}
} catch (e) {
print(e.toString());
setState(() {
_avatarFile = null;
});
}
}
其间这儿有一个小bug,当咱们挑选模拟器中的第一个相片的时分;会报错,所以在此刻加了异常处理
温馨提示:记得要在iOS的info.plist文件中装备相册的权限!