“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022”
Mixed development approach
When it comes to mixed development, we know of two types:
- Flutter calls native functions, such as photo albums
- Some native project features or pages that use Flutter(not recommended) are not recommended because unlike Web pages, Flutter is lightweight and can be embedded because of its independent rendering engine.
Flutter call native
Let’s use the personal center profile picture in the previous wechat Demo as an example. When clicking the profile picture, the native album will wake up.
GestureDetector(
onTap: () {
print('Need to evoke native camera');
_methodChannel.invokeMapMethod('takePhotos');
},
child: Container(
width: 70,
height: 70,
decoration: BoxDecoration(
image:
DecorationImage(image: AssetImage('images/game 2. PNG')),
borderRadius: BorderRadius.circular(10)),),),Copy the code
Communication in Flutter and iOS provides a special MethodChannel class to communicate with
MethodChannel _methodChannel = MethodChannel('mine/method');
Copy the code
Call when onTap _methodChannel. InvokeMapMethod (‘ takePhotos’); Tell iOS native I’m sending you a takePhotos method, iOS you need to set up your own camera for me when you receive this logo
Here we come to the iOS project:
- Let’s start by exemplifying
FlutterMethodChannel
This class, the first argument to this class is to specify which path the method is on - call
setMethodCallHandler
In response to the messages that Flutter sends - Identify the current method for processing
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var pickVc = UIImagePickerController(a)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
// Also start the communication class on iOS
flutterChannel = FlutterMethodChannel.init(name: "mine/method", binaryMessenger: vc as! FlutterBinaryMessenger)
// Handle the communication sent from the Flutter end
flutterChannel.setMethodCallHandler { call, result in
// if I identify the method as' takePhotos' I call up the native camera
if call.method.isEqual("takePhotos") {print("Here comes the way.");
self.pickVc.delegate = self
vc?.present(self.pickVc, animated: true, completion: nil)}}return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Copy the code
- Of course, select the photo in iOS and upload the information from the photo back to Flutter
invokeMethod
Comes back
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)}}Copy the code
5.Flutter also responds to setMethodCallHandler when it receives the image selected by the iOS native
@override
void initState() {
// TODO: implement initState
super.initState();
_methodChannel.setMethodCallHandler((call) {
if (call.method == 'editedImage') {
print(call.arguments);
}
return call.arguments;
});
}
Copy the code
At this point, the communication between the two ends is complete and we can replace the current image with the obtained photo path.
@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/game 2. PNG') asImageProvider : FileImage(_avatarFile!) , fit: BoxFit.cover), borderRadius: BorderRadius.circular(10))Copy the code
image_picker
There’s another way to use itpub
To wake up the camera, using a library that Flutter officially producesimage_picker
After we install can refer to the usage, the use of this article is relatively simple
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; }); }}Copy the code
There’s a little bug here, when we select the first photo in the simulator; An error is reported, so exception handling is added at this point
Tips: Remember to configure the album permissions in the iOS info.plist file!