给image_picker添加自定义UI拍摄页面
-
情形
插件常见使用:
dependencies:
image_picker: ^0.8.4+11
但是在特殊情况下,比如拍摄身份证,我们需要自定义拍摄的UI页面以满足需求,但它本身是没有这个功能的。
这种情况下就需要我们去修改插件添加我们所需要的功能。
-
分析(以iOS为例)
在"FLTImagePickerPlugin.m"文件中,关于"pickImage"方法的"imageSource"只有"SOURCE_GALLERY"和"SOURCE_CAMERA"两种:
if ([@"pickImage" isEqualToString:call.method]) {
int imageSource = [call.arguments[@"source"] intValue];
if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker
if (@available(iOS 14, *)) {
// PHPicker is used
[self pickImageWithPHPicker:1];
} else {
// UIImagePicker is used
[self launchUIImagePickerWithSource:imageSource];
}
} else {
[self launchUIImagePickerWithSource:imageSource];
}
}
查看代码发现,image_picker插件中引入的另一个插件"image_picker_platform_interface"。如下所示:
dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.1
image_picker_for_web: ^2.1.0
image_picker_platform_interface: ^2.3.0 //image_picker插件的通用平台界面
而上面两种类型对应的"image_picker_platform_interface"中的"image_source.dart"文件中的ImageSource类型,如下所示:
enum ImageSource {
/// Opens up the device camera, letting the user to take a new picture.
camera,
/// Opens the user's photo gallery.
gallery,
}
所以,想在"FLTImagePickerPlugin.m"文件中给"pickImage"方法的imageSource增加类型,就需要在插件"image_picker_platform_interface"中的imageSource添加类型。由于插件"image_picker_platform_interface"是自动引入到插件"image_picker"中的,所以,要将修改后的插件"image_picker_platform_interface"以本地引入的形式引入,然后在"FLTImagePickerPlugin.m"文件中根据需要做逻辑处理。
-
修改(以iOS为例)
1、把插件 "image_picker_platform_interface"改为本地引入
在插件"image_picker"中创建文件夹"plugins",下载插件"image_picker_platform_interface-2.4.4",然后放入plugins中,最后本地引入。
dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.1
image_picker_for_web: ^2.1.0
# image_picker_platform_interface: ^2.3.0
image_picker_platform_interface:
path: ./plugins/image_picker_platform_interface-2.4.4
image.png
2、将"image_picker_for_web"注释掉
Pub get报如下错误:
Running "flutter pub get" in image_picker-0.8.4+11...
Because image_picker depends on image_picker_for_web ^2.1.0 which depends on image_picker_platform_interface ^2.2.0, image_picker_platform_interface from hosted is required.
So, because image_picker depends on image_picker_platform_interface from path, version solving failed.
pub get failed (1; So, because image_picker depends on image_picker_platform_interface from path, version solving failed.)
Process finished with exit code 1
是指"image_picker_for_web"和"image_picker_platform_interface"版本不兼容,这里方便起见,将其注释掉,如果需要其功能的话,可将image_picker_platform_interface改成与image_picker_for_web不冲突的版本,其他步骤不变。
dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.1
# image_picker_for_web: ^2.1.0
# image_picker_platform_interface: ^2.3.0
image_picker_platform_interface:
path: ./plugins/image_picker_platform_interface-2.4.4
3、给ImageSource添加类型
以添加自定义拍摄身份证正反面UI为例,添加SOURCE_FRONT_IDImage和SOURCE_BACK_IDImage两种类型。根据需要添加,名字自己定义。
enum ImageSource {
/// Opens up the device camera, letting the user to take a new picture.
camera,
/// Opens the user's photo gallery.
gallery,
//自己需要增加的
SOURCE_FRONT_IDImage,
SOURCE_BACK_IDImage
}
image.png
4、将自定义文件放入插件对应的位置
添加完成后,在example的iOS下执行"pod install",使修改的"image_picker.podspec"生效。
5、在"FLTImagePickerPlugin.m"添加逻辑处理
导入自定义类头文件
#import "CameraVC.h"
#import "FileManager.h"
添加Type类型:
static const int SOURCE_CAMERA = 0;
static const int SOURCE_GALLERY = 1;
static const int SOURCE_FRONT_IDImage = 2;//添加的
static const int SOURCE_BACK_IDImage = 3;//添加的
然后添加逻辑处理:
if ([@"pickImage" isEqualToString:call.method]) {
int imageSource = [call.arguments[@"source"] intValue];
if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker
if (@available(iOS 14, *)) {
// PHPicker is used
[self pickImageWithPHPicker:1];
} else {
// UIImagePicker is used
[self launchUIImagePickerWithSource:imageSource];
}
} else if (imageSource == SOURCE_CAMERA){
[self launchUIImagePickerWithSource:imageSource];
}
//自己定义的,再此做逻辑处理 跳到自定义UI页面
else if (imageSource == SOURCE_FRONT_IDImage){
//身份证正面
CameraVC *vc = [[CameraVC alloc] init];
vc.isBack = false;
vc.imageblock = ^(UIImage * _Nonnull image) {
//返回图片路径
NSString *fileName = [NSString stringWithFormat:@"idCardFront-%d",arc4random()];
result([FileManager storeImage:UIImageJPEGRepresentation(image, 0.4f) withImageName:fileName]);
};
[[UIApplication sharedApplication].keyWindow.rootViewController addChildViewController:vc];
[[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:vc.view];
} else if (imageSource == SOURCE_BACK_IDImage){
//身份证反面
CameraVC *vc = [[CameraVC alloc] init];
vc.isBack = YES;
vc.imageblock = ^(UIImage * _Nonnull image) {
//返回图片路径
NSString *fileName = [NSString stringWithFormat:@"idCardBack-%d",arc4random()];
result([FileManager storeImage:UIImageJPEGRepresentation(image, 0.4f) withImageName:fileName]);
};
[[UIApplication sharedApplication].keyWindow.rootViewController addChildViewController:vc];
[[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:vc.view];
}
} else if ([@"pickMultiImage" isEqualToString:call.method]) {}
同样,android部分按照iOS的逻辑类似处理,具体可看文章尾部的demo。
整体目录如下图所示:
image.png
-
使用
在需要使用自定义拍摄UI的时候,source选用自己添加定义的ImageSource.SOURCE_FRONT_IDImage 或 ImageSource.SOURCE_BACK_IDImage:
final ImagePicker _picker = ImagePicker();
// Pick an image
final XFile? image2 = await _picker.pickImage(source: ImageSource.SOURCE_FRONT_IDImage);
-
效果
人像面:
1.jpg | 2.jpg | 3.jpg |
---|
国徽面:
1.jpg | 2.jpg | 3.jpg |
---|
Github的Demo地址:flutter_image_picker_custom_demo