Commit 25a30fd3 authored by CookieJ's avatar CookieJ

添加支持Promise调用的 asyncShowImagePicker 方法

parent bf222ee2
...@@ -8,6 +8,7 @@ import android.graphics.BitmapFactory; ...@@ -8,6 +8,7 @@ import android.graphics.BitmapFactory;
import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener; import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
...@@ -27,11 +28,15 @@ import java.util.List; ...@@ -27,11 +28,15 @@ import java.util.List;
public class RNSyanImagePickerModule extends ReactContextBaseJavaModule { public class RNSyanImagePickerModule extends ReactContextBaseJavaModule {
private static String SY_SELECT_IMAGE_FAILED_CODE = "0"; // 失败时,Promise用到的code
private final ReactApplicationContext reactContext; private final ReactApplicationContext reactContext;
private List<LocalMedia> selectList = new ArrayList<>(); private List<LocalMedia> selectList = new ArrayList<>();
private Callback mPickerCallback; private Callback mPickerCallback; // 保存回调
private Promise mPickerPromise; // 保存Promise
public RNSyanImagePickerModule(ReactApplicationContext reactContext) { public RNSyanImagePickerModule(ReactApplicationContext reactContext) {
super(reactContext); super(reactContext);
...@@ -46,6 +51,24 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule { ...@@ -46,6 +51,24 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule {
@ReactMethod @ReactMethod
public void showImagePicker(ReadableMap options, Callback callback) { public void showImagePicker(ReadableMap options, Callback callback) {
this.mPickerPromise = null;
this.mPickerCallback = callback;
this.openImagePicker(options);
}
@ReactMethod
public void asyncShowImagePicker(ReadableMap options, Promise promise) {
this.mPickerCallback = null;
this.mPickerPromise = promise;
this.openImagePicker(options);
}
/**
* 打开相册选择
*
* @param options 相册参数
*/
private void openImagePicker(ReadableMap options) {
int imageCount = options.getInt("imageCount"); int imageCount = options.getInt("imageCount");
boolean isCamera = options.getBoolean("isCamera"); boolean isCamera = options.getBoolean("isCamera");
boolean isCrop = options.getBoolean("isCrop"); boolean isCrop = options.getBoolean("isCrop");
...@@ -62,8 +85,6 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule { ...@@ -62,8 +85,6 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule {
} else { } else {
modeValue = 2; modeValue = 2;
} }
this.mPickerCallback = callback;
Activity currentActivity = getCurrentActivity(); Activity currentActivity = getCurrentActivity();
PictureSelector.create(currentActivity) PictureSelector.create(currentActivity)
.openGallery(PictureMimeType.ofImage())// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio() .openGallery(PictureMimeType.ofImage())// 全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio()
...@@ -90,7 +111,6 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule { ...@@ -90,7 +111,6 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule {
.cropCompressQuality(90)// 裁剪压缩质量 默认100 .cropCompressQuality(90)// 裁剪压缩质量 默认100
.scaleEnabled(true)// 裁剪是否可放大缩小图片 .scaleEnabled(true)// 裁剪是否可放大缩小图片
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code .forResult(PictureConfig.CHOOSE_REQUEST);//结果回调onActivityResult code
} }
private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() { private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
...@@ -130,12 +150,37 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule { ...@@ -130,12 +150,37 @@ public class RNSyanImagePickerModule extends ReactContextBaseJavaModule {
imageList.pushMap(aImage); imageList.pushMap(aImage);
} }
if (selectList.isEmpty()) { if (selectList.isEmpty()) {
mPickerCallback.invoke("取消"); invokeError();
} else { } else {
mPickerCallback.invoke(null, imageList); invokeSuccessWithResult(imageList);
} }
} }
} }
}; };
/**
* 选择照片成功时触发
*
* @param imageList 图片数组
*/
private void invokeSuccessWithResult(WritableArray imageList) {
if (this.mPickerCallback != null) {
this.mPickerCallback.invoke(null, imageList);
this.mPickerCallback = null;
} else if (this.mPickerPromise != null) {
this.mPickerPromise.resolve(imageList);
}
}
/**
* 取消选择时触发
*/
private void invokeError() {
if (this.mPickerCallback != null) {
this.mPickerCallback.invoke("取消");
this.mPickerCallback = null;
} else if (this.mPickerPromise != null) {
this.mPickerPromise.reject(SY_SELECT_IMAGE_FAILED_CODE, "取消");
}
}
} }
\ No newline at end of file
import { import {
NativeModules, NativeModules,
Platform,
Dimensions, Dimensions,
} from 'react-native'; } from 'react-native';
const {RNSyanImagePicker} = NativeModules; const { RNSyanImagePicker } = NativeModules;
const {width, height} = Dimensions.get('window'); const { width } = Dimensions.get('window');
/**
* 默认参数
*/
const defaultOptions = {
imageCount: 2, // 最大选择图片数目,默认1
isCamera: true, // 是否允许用户在内部拍照,默认true
isCrop: false, // 是否允许裁剪,默认false
CropW: ~~(width * 0.6), // 裁剪宽度,默认屏幕宽度60%
CropH: ~~(width * 0.6), // 裁剪高度,默认屏幕宽度60%
isGif: false, // 是否允许选择GIF,默认false
showCropCircle: false, // 是否显示圆形裁剪区域,默认false
showCropFrame: true, // 是否显示裁剪区域,默认true
showCropGrid: false, // 是否隐藏裁剪区域网格,默认false
};
export default { export default {
showImagePicker(options, bc) { /**
* 以Callback形式调用
* 1、相册参数暂时只支持默认参数中罗列的属性;
* 2、回调形式:showImagePicker(options, (err, selectedPhotos) => {})
* 1)选择图片成功,err为null,selectedPhotos为选中的图片数组
* 2)取消时,err返回"取消",selectedPhotos将为undefined
* 按需判断各参数值,确保调用正常,示例使用方式:
* showImagePicker(options, (err, selectedPhotos) => {
* if (err) {
* // 取消选择
* return;
* }
* // 选择成功
* })
*
* @param {Object} options 相册参数
* @param {Function} callback 成功,或失败回调
*/
showImagePicker(options, callback) {
const optionObj = { const optionObj = {
imageCount: 1, ...defaultOptions,
isCamera: true,
isCrop: false,
CropW: ~~(width*0.6),
CropH: ~~(width*0.6),
isGif: false,
showCropCircle: false,
showCropFrame: true,
showCropGrid: false,
...options ...options
} };
RNSyanImagePicker.showImagePicker(optionObj, callback)
return RNSyanImagePicker.showImagePicker(optionObj, bc) },
/**
* 以Promise形式调用
* 1、相册参数暂时只支持默认参数中罗列的属性;
* 2、使用方式
* 1)async/await
* handleSelectPhoto = async () => {
* try {
* const photos = await SYImagePicker.asyncShowImagePicker(options);
* // 选择成功
* } catch (err) {
* // 取消选择,err.message为"取消"
* }
* }
* 2)promise.then形式
* handleSelectPhoto = () => {
* SYImagePicker.asyncShowImagePicker(options)
* .then(photos => {
* // 选择成功
* })
* .catch(err => {
* // 取消选择,err.message为"取消"
* })
* }
* @param {Object} options 相册参数
* @return {Promise} 返回一个Promise对象
*/
asyncShowImagePicker(options) {
const optionObj = {
...defaultOptions,
...options,
};
return RNSyanImagePicker.asyncShowImagePicker(optionObj);
} }
}; };
//
// NSMutableDictionary+SYSafeConvert.h
// RNSyanImagePicker
//
// Created by CookieJ on 2017/10/18.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableDictionary (SYSafeConvert)
- (void)sy_setObject:(id)value forKey:(NSString *)key;
- (void)sy_setInteger:(NSInteger)value forKey:(NSString *)key;
- (void)sy_setBool:(BOOL)value forKey:(NSString *)key;
@end
@interface NSDictionary (SYSafeConvert)
- (NSString *)sy_stringForKey:(NSString *)key;
- (BOOL)sy_boolForKey:(NSString *)key;
- (NSInteger)sy_integerForKey:(NSString *)key;
@end
//
// NSMutableDictionary+SYSafeConvert.m
// RNSyanImagePicker
//
// Created by CookieJ on 2017/10/18.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "NSMutableDictionary+SYSafeConvert.h"
@implementation NSMutableDictionary (SYSafeConvert)
- (void)sy_setObject:(id)value forKey:(NSString *)key {
if (![self isKindOfClass:[NSMutableDictionary class]]) {
NSLog(@"类型有误,非字典无法设置值!");
return;
}
if (value && value != [NSNull null] && key) {
[self setObject:value forKey:key];
}
}
- (void)sy_setBool:(BOOL)value forKey:(NSString *)key {
if (![self isKindOfClass:[NSMutableDictionary class]]) {
NSLog(@"类型有误,非字典无法设置值!");
return;
}
if (key) {
[self setObject:@(value) forKey:key];
}
}
- (void)sy_setInteger:(NSInteger)value forKey:(NSString *)key {
if (![self isKindOfClass:[NSMutableDictionary class]]) {
NSLog(@"类型有误,非字典无法设置值!");
return;
}
if (key) {
[self setObject:@(value) forKey:key];
}
}
@end
@implementation NSDictionary (SYSafeConvert)
- (BOOL)sy_boolForKey:(NSString *)key {
if (![self isKindOfClass:[NSDictionary class]]) {
NSLog(@"类型有误,无法从非字典取值!");
return nil;
}
id value = [self objectForKey:key];
if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) {
return [value boolValue];
}
return NO;
}
- (NSInteger)sy_integerForKey:(NSString *)key {
if (![self isKindOfClass:[NSDictionary class]]) {
NSLog(@"类型有误,无法从非字典取值!");
return nil;
}
id value = [self objectForKey:key];
if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) {
return [value integerValue];
}
return 0;
}
- (NSString *)sy_stringForKey:(NSString *)key {
if (![self isKindOfClass:[NSDictionary class]]) {
NSLog(@"类型有误,无法从非字典取值!");
return nil;
}
id value = [self objectForKey:key];
if ([value isKindOfClass:[NSString class]]) {
return (NSString *)value;
}
if ([value isKindOfClass:[NSNumber class]]) {
return [value stringValue];
}
return nil;
}
@end
#import "RNSyanImagePicker.h" #import "RNSyanImagePicker.h"
#import "TZImagePickerController.h" #import "TZImagePickerController.h"
#import "NSDictionary+SYSafeConvert.h"
@interface RNSyanImagePicker ()
/**
保存Promise的resolve block
*/
@property (nonatomic, copy) RCTPromiseResolveBlock resolveBlock;
/**
保存Promise的reject block
*/
@property (nonatomic, copy) RCTPromiseRejectBlock rejectBlock;
/**
保存回调的callback
*/
@property (nonatomic, copy) RCTResponseSenderBlock callback;
@end
@implementation RNSyanImagePicker @implementation RNSyanImagePicker
...@@ -8,23 +24,32 @@ RCT_EXPORT_MODULE() ...@@ -8,23 +24,32 @@ RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options
callback:(RCTResponseSenderBlock)callback) { callback:(RCTResponseSenderBlock)callback) {
self.callback = callback;
self.resolveBlock = nil;
self.rejectBlock = nil;
[self openImagePickerWithOptions:options];
}
//照片最大可选张数 RCT_REMAP_METHOD(asyncShowImagePicker,
NSInteger imageCount = [options[@"imageCount"] integerValue]; options:(NSDictionary *)options
resolver:(RCTPromiseResolveBlock)resolve
//显示内部拍照按钮 rejecter:(RCTPromiseRejectBlock)reject) {
BOOL isCamera = [options[@"isCamera"] boolValue]; self.resolveBlock = resolve;
self.rejectBlock = reject;
BOOL isCrop = [options[@"isCrop"] boolValue]; self.callback = nil;
[self openImagePickerWithOptions:options];
NSInteger CropW = [options[@"CropW"] integerValue]; }
NSInteger CropH = [options[@"CropH"] integerValue];
BOOL isGif = [options[@"isGif"] boolValue];
BOOL showCropCircle = [options[@"showCropCircle"] boolValue];
- (void)openImagePickerWithOptions:(NSDictionary *)options {
// 照片最大可选张数
NSInteger imageCount = [options sy_integerForKey:@"imageCount"];
// 显示内部拍照按钮
BOOL isCamera = [options sy_boolForKey:@"isCamera"];
BOOL isCrop = [options sy_boolForKey:@"isCrop"];
BOOL isGif = [options sy_boolForKey:@"isGif"];
BOOL showCropCircle = [options sy_boolForKey:@"showCropCircle"];
NSInteger CropW = [options sy_integerForKey:@"CropW"];
NSInteger CropH = [options sy_integerForKey:@"CropH"];
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:imageCount delegate:nil]; TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:imageCount delegate:nil];
...@@ -39,8 +64,8 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options ...@@ -39,8 +64,8 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options
// 单选模式 // 单选模式
imagePickerVc.showSelectBtn = NO; imagePickerVc.showSelectBtn = NO;
imagePickerVc.allowPreview = NO; imagePickerVc.allowPreview = NO;
if(isCrop){
if(isCrop){
if(showCropCircle) { if(showCropCircle) {
imagePickerVc.needCircleCrop = showCropCircle; //圆形裁剪 imagePickerVc.needCircleCrop = showCropCircle; //圆形裁剪
} else { } else {
...@@ -91,18 +116,46 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options ...@@ -91,18 +116,46 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options
}]; }];
} }
callback(@[[NSNull null],[NSArray arrayWithArray:selectedPhotos]]); [self invokeSuccessWithResult:selectedPhotos];
[weakPicker hideProgressHUD]; [weakPicker hideProgressHUD];
}]; }];
[imagePickerVc setImagePickerControllerDidCancelHandle:^{ [imagePickerVc setImagePickerControllerDidCancelHandle:^{
callback(@[@"取消"]); [self invokeError];
}]; }];
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:imagePickerVc animated:YES completion:nil]; [[self topViewController] presentViewController:imagePickerVc animated:YES completion:nil];
}
- (void)invokeSuccessWithResult:(NSArray *)photos {
if (self.callback) {
self.callback(@[[NSNull null], photos]);
self.callback = nil;
}
if (self.resolveBlock) {
self.resolveBlock(photos);
self.resolveBlock = nil;
}
}
- (void)invokeError {
if (self.callback) {
self.callback(@[@"取消"]);
self.callback = nil;
}
if (self.rejectBlock) {
self.rejectBlock(@"", @"取消", nil);
self.rejectBlock = nil;
}
}
- (UIViewController *)topViewController {
UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
if (rootViewController.presentedViewController) {
rootViewController = rootViewController.presentedViewController;
}
return rootViewController;
} }
- (dispatch_queue_t)methodQueue - (dispatch_queue_t)methodQueue
...@@ -110,6 +163,4 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options ...@@ -110,6 +163,4 @@ RCT_EXPORT_METHOD(showImagePicker:(NSDictionary *)options
return dispatch_get_main_queue(); return dispatch_get_main_queue();
} }
@end @end
\ No newline at end of file
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
23F50D731F3C041A004B3E61 /* TZVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 23F50D641F3C041A004B3E61 /* TZVideoPlayerController.m */; }; 23F50D731F3C041A004B3E61 /* TZVideoPlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 23F50D641F3C041A004B3E61 /* TZVideoPlayerController.m */; };
23F50D741F3C041A004B3E61 /* UIView+Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = 23F50D661F3C041A004B3E61 /* UIView+Layout.m */; }; 23F50D741F3C041A004B3E61 /* UIView+Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = 23F50D661F3C041A004B3E61 /* UIView+Layout.m */; };
B3E7B58A1CC2AC0600A0062D /* RNSyanImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */; }; B3E7B58A1CC2AC0600A0062D /* RNSyanImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */; };
EC236E871F978C3B00D528A5 /* NSDictionary+SYSafeConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = EC236E861F978C3B00D528A5 /* NSDictionary+SYSafeConvert.m */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
...@@ -69,6 +70,8 @@ ...@@ -69,6 +70,8 @@
23F50D661F3C041A004B3E61 /* UIView+Layout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Layout.m"; sourceTree = "<group>"; }; 23F50D661F3C041A004B3E61 /* UIView+Layout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Layout.m"; sourceTree = "<group>"; };
B3E7B5881CC2AC0600A0062D /* RNSyanImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSyanImagePicker.h; sourceTree = "<group>"; }; B3E7B5881CC2AC0600A0062D /* RNSyanImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSyanImagePicker.h; sourceTree = "<group>"; };
B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSyanImagePicker.m; sourceTree = "<group>"; }; B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSyanImagePicker.m; sourceTree = "<group>"; };
EC236E851F978C3B00D528A5 /* NSDictionary+SYSafeConvert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SYSafeConvert.h"; sourceTree = "<group>"; };
EC236E861F978C3B00D528A5 /* NSDictionary+SYSafeConvert.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SYSafeConvert.m"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
...@@ -129,6 +132,8 @@ ...@@ -129,6 +132,8 @@
58B511D21A9E6C8500147676 = { 58B511D21A9E6C8500147676 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EC236E851F978C3B00D528A5 /* NSDictionary+SYSafeConvert.h */,
EC236E861F978C3B00D528A5 /* NSDictionary+SYSafeConvert.m */,
23F50D491F3C0419004B3E61 /* TZImagePickerController */, 23F50D491F3C0419004B3E61 /* TZImagePickerController */,
B3E7B5881CC2AC0600A0062D /* RNSyanImagePicker.h */, B3E7B5881CC2AC0600A0062D /* RNSyanImagePicker.h */,
B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */, B3E7B5891CC2AC0600A0062D /* RNSyanImagePicker.m */,
...@@ -198,6 +203,7 @@ ...@@ -198,6 +203,7 @@
23F50D6C1F3C041A004B3E61 /* TZImageManager.m in Sources */, 23F50D6C1F3C041A004B3E61 /* TZImageManager.m in Sources */,
23F50D671F3C041A004B3E61 /* NSBundle+TZImagePicker.m in Sources */, 23F50D671F3C041A004B3E61 /* NSBundle+TZImagePicker.m in Sources */,
23F50D6A1F3C041A004B3E61 /* TZGifPhotoPreviewController.m in Sources */, 23F50D6A1F3C041A004B3E61 /* TZGifPhotoPreviewController.m in Sources */,
EC236E871F978C3B00D528A5 /* NSDictionary+SYSafeConvert.m in Sources */,
23F50D6B1F3C041A004B3E61 /* TZImageCropManager.m in Sources */, 23F50D6B1F3C041A004B3E61 /* TZImageCropManager.m in Sources */,
23F50D711F3C041A004B3E61 /* TZPhotoPreviewController.m in Sources */, 23F50D711F3C041A004B3E61 /* TZPhotoPreviewController.m in Sources */,
23F50D741F3C041A004B3E61 /* UIView+Layout.m in Sources */, 23F50D741F3C041A004B3E61 /* UIView+Layout.m in Sources */,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment