add qrcode界面和功能
BIN
Classes_cocos/LBXNative/CodeScan.bundle/device_scan@2x.png
Normal file
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 1.5 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_flash_down@2x.png
Executable file
After Width: | Height: | Size: 938 B |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_flash_nor@2x.png
Executable file
After Width: | Height: | Size: 1.1 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_myqrcode_down@2x.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_myqrcode_nor@2x.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_photo_down@2x.png
Executable file
After Width: | Height: | Size: 980 B |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_photo_nor@2x.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_btn_scan_off@2x.png
Executable file
After Width: | Height: | Size: 956 B |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_full_net.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_light_green@2x.png
Executable file
After Width: | Height: | Size: 801 B |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_part_net.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_titlebar_back_nor@2x.png
Executable file
After Width: | Height: | Size: 185 B |
BIN
Classes_cocos/LBXNative/CodeScan.bundle/qrcode_scan_titlebar_back_pressed@2x.png
Executable file
After Width: | Height: | Size: 164 B |
9
Classes_cocos/LBXNative/CreateBarCodeViewController.h
Normal file
@ -0,0 +1,9 @@
|
||||
//
|
||||
// CreateBarCodeViewController.h
|
||||
// LBXScanDemo
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CreateBarCodeViewController : UIViewController
|
||||
|
||||
@end
|
181
Classes_cocos/LBXNative/CreateBarCodeViewController.m
Normal file
@ -0,0 +1,181 @@
|
||||
//
|
||||
// CreateBarCodeViewController.m
|
||||
// LBXScanDemo
|
||||
//
|
||||
|
||||
#import "CreateBarCodeViewController.h"
|
||||
#import "LBXScanNative.h"
|
||||
#import "UIImageView+CornerRadius.h"
|
||||
|
||||
@interface CreateBarCodeViewController ()
|
||||
|
||||
//二维码
|
||||
@property (nonatomic, strong) UIView *qrView;
|
||||
@property (nonatomic, strong) UIImageView* qrImgView;
|
||||
@property (nonatomic, strong) UIImageView* logoImgView;
|
||||
|
||||
//条形码
|
||||
@property (nonatomic, strong) UIView *tView;
|
||||
@property (nonatomic, strong) UIImageView *tImgView;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation CreateBarCodeViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
[self showSetttingButton];
|
||||
}
|
||||
|
||||
- (void)showSetttingButton
|
||||
{
|
||||
//选择码扫码类型的按钮
|
||||
//把右侧的两个按钮添加到rightBarButtonItem
|
||||
UIButton *rightBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 40, 30)];
|
||||
[rightBtn setTitle:@"切换" forState:UIControlStateNormal];
|
||||
[rightBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
|
||||
[rightBtn addTarget:self action:@selector(newCodeChooose) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
UIBarButtonItem *rightCunstomButtonView = [[UIBarButtonItem alloc] initWithCustomView:rightBtn];
|
||||
self.navigationItem.rightBarButtonItem = rightCunstomButtonView;
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
//二维码
|
||||
UIView *view = [[UIView alloc]initWithFrame:CGRectMake( (CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.view.frame)*5/6)/2, 100, CGRectGetWidth(self.view.frame)*5/6, CGRectGetWidth(self.view.frame)*5/6)];
|
||||
[self.view addSubview:view];
|
||||
view.backgroundColor = [UIColor whiteColor];
|
||||
view.layer.shadowOffset = CGSizeMake(0, 2);
|
||||
view.layer.shadowRadius = 2;
|
||||
view.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
view.layer.shadowOpacity = 0.5;
|
||||
|
||||
|
||||
self.qrImgView = [[UIImageView alloc]init];
|
||||
_qrImgView.bounds = CGRectMake(0, 0, CGRectGetWidth(view.frame)-12, CGRectGetWidth(view.frame)-12);
|
||||
_qrImgView.center = CGPointMake(CGRectGetWidth(view.frame)/2, CGRectGetHeight(view.frame)/2);
|
||||
[view addSubview:_qrImgView];
|
||||
self.qrView = view;
|
||||
|
||||
|
||||
//条形码
|
||||
self.tView = [[UIView alloc]initWithFrame:CGRectMake( (CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.view.frame)*5/6)/2,
|
||||
100,
|
||||
CGRectGetWidth(self.view.frame)*5/6,
|
||||
CGRectGetWidth(self.view.frame)*5/6*0.5)];
|
||||
[self.view addSubview:_tView];
|
||||
|
||||
|
||||
self.tImgView = [[UIImageView alloc]init];
|
||||
_tImgView.bounds = CGRectMake(0, 0, CGRectGetWidth(_tView.frame)-12, CGRectGetHeight(_tView.frame)-12);
|
||||
_tImgView.center = CGPointMake(CGRectGetWidth(_tView.frame)/2, CGRectGetHeight(_tView.frame)/3);
|
||||
[_tView addSubview:_tImgView];
|
||||
|
||||
|
||||
[self createQR_logo];
|
||||
|
||||
}
|
||||
|
||||
- (void)newCodeChooose
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
// [LBXAlertAction showActionSheetWithTitle:@"" message:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitle:@[@"二维码+logo",@"二维码前景颜色+背景颜色",@"code13-商品条形码",@"支付宝付款条形码(code128)"] chooseBlock:^(NSInteger buttonIdx) {
|
||||
//
|
||||
// switch (buttonIdx) {
|
||||
//
|
||||
// case 1:
|
||||
// [weakSelf createQR_logo];
|
||||
// break;
|
||||
// case 2:
|
||||
// [weakSelf createQR_color];
|
||||
// break;
|
||||
// case 3:
|
||||
// [weakSelf createCodeEAN13];
|
||||
// break;
|
||||
// case 4:
|
||||
// [weakSelf createCode128];
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }];
|
||||
}
|
||||
|
||||
|
||||
- (void)createQR_logo
|
||||
{
|
||||
_qrView.hidden = NO;
|
||||
_tView.hidden = YES;
|
||||
|
||||
|
||||
_qrImgView.image = [LBXScanNative createQRWithString:@"lbxia20091227@foxmail.com" QRSize:_qrImgView.bounds.size];
|
||||
|
||||
CGSize logoSize=CGSizeMake(30, 30);
|
||||
self.logoImgView = [self roundCornerWithImage:[UIImage imageNamed:@"logo"] size:logoSize];
|
||||
_logoImgView.bounds = CGRectMake(0, 0, logoSize.width, logoSize.height);
|
||||
_logoImgView.center = CGPointMake(CGRectGetWidth(_qrImgView.frame)/2, CGRectGetHeight(_qrImgView.frame)/2);
|
||||
[_qrImgView addSubview:_logoImgView];
|
||||
}
|
||||
|
||||
- (UIImageView*)roundCornerWithImage:(UIImage*)logoImg size:(CGSize)size
|
||||
{
|
||||
//logo圆角
|
||||
UIImageView *backImage = [[UIImageView alloc] initWithCornerRadiusAdvance:6.0f rectCornerType:UIRectCornerAllCorners];
|
||||
backImage.frame = CGRectMake(0, 0, size.width, size.height);
|
||||
backImage.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
UIImageView *logImage = [[UIImageView alloc] initWithCornerRadiusAdvance:6.0f rectCornerType:UIRectCornerAllCorners];
|
||||
logImage.image =logoImg;
|
||||
CGFloat diff =2;
|
||||
logImage.frame = CGRectMake(diff, diff, size.width - 2 * diff, size.height - 2 * diff);
|
||||
|
||||
[backImage addSubview:logImage];
|
||||
|
||||
return backImage;
|
||||
}
|
||||
|
||||
- (void)createQR_color
|
||||
{
|
||||
_qrView.hidden = NO;
|
||||
_tView.hidden = YES;
|
||||
|
||||
_qrImgView.image = [LBXScanNative createQRWithString:@"" QRSize:_qrImgView.bounds.size QRColor:[UIColor blueColor] bkColor:[UIColor whiteColor]];
|
||||
}
|
||||
|
||||
//商品条形码
|
||||
- (void)createCodeEAN13
|
||||
{
|
||||
_qrView.hidden = YES;
|
||||
_tView.hidden = NO;
|
||||
|
||||
[self showError:@"native暂不支持EAN13条形码"];
|
||||
}
|
||||
|
||||
- (void)createCode128
|
||||
{
|
||||
_qrView.hidden = YES;
|
||||
_tView.hidden = NO;
|
||||
|
||||
_tImgView.image = [LBXScanNative createBarCodeWithString:@"283657461695996598" QRSize:_qrImgView.bounds.size];
|
||||
}
|
||||
|
||||
- (void)showError:(NSString*)str
|
||||
{
|
||||
// [LBXAlertAction showAlertWithTitle:@"提示" msg:str buttonsStatement:@[@"知道了"] chooseBlock:nil];
|
||||
}
|
||||
|
||||
|
||||
@end
|
97
Classes_cocos/LBXNative/LBXScanBaseViewController.h
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// LBXScanBaseViewController.h
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "LBXScanTypes.h"
|
||||
#import "LBXScanView.h"
|
||||
#import "LBXScanNative.h"
|
||||
|
||||
|
||||
@interface LBXScanBaseViewController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
|
||||
#pragma mark ---- 需要初始化参数 ------
|
||||
|
||||
|
||||
/**
|
||||
@brief 是否需要扫码图像
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isNeedScanImage;
|
||||
|
||||
|
||||
/**
|
||||
@brief 是否需要连续扫码
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL continuous;
|
||||
|
||||
/**
|
||||
@brief 启动区域识别功能
|
||||
*/
|
||||
@property(nonatomic,assign) BOOL isOpenInterestRect;
|
||||
|
||||
|
||||
/**
|
||||
相机启动提示,如 相机启动中...
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *cameraInvokeMsg;
|
||||
|
||||
|
||||
//相机预览
|
||||
@property (nonatomic, strong) UIView *cameraPreView;
|
||||
|
||||
/**
|
||||
* 界面效果参数
|
||||
*/
|
||||
@property (nonatomic, strong) LBXScanViewStyle *style;
|
||||
|
||||
//default AVCaptureVideoOrientationPortrait
|
||||
@property (nonatomic, assign) AVCaptureVideoOrientation orientation;
|
||||
|
||||
/**
|
||||
@brief 扫码区域视图,二维码一般都是框
|
||||
*/
|
||||
@property (nonatomic,strong) LBXScanView* qRScanView;
|
||||
|
||||
|
||||
/// 首次加载
|
||||
@property (nonatomic, assign) BOOL firstLoad;
|
||||
|
||||
//条码识别位置标示
|
||||
@property (nonatomic, strong) UIView *codeFlagView;
|
||||
@property (nonatomic, strong) NSArray<CALayer*> *layers;
|
||||
|
||||
|
||||
/**
|
||||
@brief 扫码存储的当前图片
|
||||
*/
|
||||
@property(nonatomic,strong) UIImage* scanImage;
|
||||
|
||||
|
||||
/**
|
||||
@brief 闪关灯开启状态记录
|
||||
*/
|
||||
@property(nonatomic,assign)BOOL isOpenFlash;
|
||||
|
||||
|
||||
|
||||
//继承者实现
|
||||
- (void)reStartDevice;
|
||||
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array;
|
||||
|
||||
|
||||
- (void)resetCodeFlagView;
|
||||
|
||||
///截取UIImage指定区域图片
|
||||
- (UIImage *)imageByCroppingWithSrcImage:(UIImage*)srcImg cropRect:(CGRect)cropRect;
|
||||
|
||||
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion;
|
||||
+ (void)authorizePhotoPermissionWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion;
|
||||
|
||||
|
||||
|
||||
- (BOOL)isLandScape;
|
||||
|
||||
- (AVCaptureVideoOrientation)videoOrientation;
|
||||
@end
|
||||
|
||||
|
557
Classes_cocos/LBXNative/LBXScanBaseViewController.m
Normal file
@ -0,0 +1,557 @@
|
||||
//
|
||||
// LBXScanBaseViewController.m
|
||||
//
|
||||
|
||||
#import "LBXScanBaseViewController.h"
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <Photos/Photos.h>
|
||||
#import "ScanResultViewController.h"
|
||||
//#import "LBXToast.h"
|
||||
|
||||
@interface LBXScanBaseViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation LBXScanBaseViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
self.firstLoad = YES;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChanged:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
[[NSNotificationCenter defaultCenter]removeObserver:self];
|
||||
|
||||
self.firstLoad = NO;
|
||||
}
|
||||
|
||||
- (void)statusBarOrientationChanged:(NSNotification*)notification
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark- 识别结果
|
||||
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
|
||||
{
|
||||
|
||||
if (!array || array.count < 1)
|
||||
{
|
||||
NSLog(@"失败失败了。。。。");
|
||||
NSLog(@"失败失败了。。。。");
|
||||
NSLog(@"失败失败了。。。。");
|
||||
|
||||
if (!_continuous) {
|
||||
[self reStartDevice];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//经测试,可以ZXing同时识别2个二维码,不能同时识别二维码和条形码
|
||||
// for (LBXScanResult *result in array) {
|
||||
//
|
||||
// NSLog(@"scanResult:%@",result.strScanned);
|
||||
// }
|
||||
|
||||
LBXScanResult *scanResult = array[0];
|
||||
|
||||
NSString*strResult = scanResult.strScanned;
|
||||
|
||||
|
||||
if (_continuous) {
|
||||
|
||||
if (strResult) {
|
||||
// [LBXToast showToastWithMessage:strResult];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!strResult) {
|
||||
|
||||
[self reStartDevice];
|
||||
return;
|
||||
}
|
||||
|
||||
[self.qRScanView stopScanAnimation];
|
||||
|
||||
self.scanImage = scanResult.imgScanned;
|
||||
|
||||
//TODO: 这里可以根据需要添加震动或播放成功提醒音等提示相关代码
|
||||
//...
|
||||
|
||||
//TODO:表示二维码位置
|
||||
//ZXing在开启区域识别后,当前计算方式不准确
|
||||
if (!self.isOpenInterestRect && self.cameraPreView && !CGRectEqualToRect(CGRectZero, scanResult.bounds) ) {
|
||||
|
||||
CGFloat centerX = scanResult.bounds.origin.x + scanResult.bounds.size.width / 2;
|
||||
CGFloat centerY = scanResult.bounds.origin.y + scanResult.bounds.size.height / 2;
|
||||
|
||||
//条码中心位置绘制红色正方形
|
||||
[self signCodeWithCenterX:centerX centerY:centerY];
|
||||
|
||||
//条码位置边缘绘制及内部填充
|
||||
[self didDetectCodes:scanResult.bounds corner:scanResult.corners];
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self showNextVCWithScanResult:scanResult];
|
||||
// });
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
[self showNextVCWithScanResult:scanResult];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-(UIImage *)getImageFromLayer:(CALayer *)layer size:(CGSize)size
|
||||
{
|
||||
UIGraphicsBeginImageContextWithOptions(size, YES, [[UIScreen mainScreen]scale]);
|
||||
[layer renderInContext:UIGraphicsGetCurrentContext()];
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
- (CGPoint)pointForCorner:(NSDictionary *)corner {
|
||||
CGPoint point;
|
||||
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corner, &point);
|
||||
return point;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)handCorners:(NSArray<NSDictionary *> *)corners bounds:(CGRect)bounds
|
||||
{
|
||||
CGFloat totalX = 0;
|
||||
CGFloat totalY = 0;
|
||||
|
||||
for (NSDictionary *dic in corners) {
|
||||
CGPoint pt = [self pointForCorner:dic];
|
||||
NSLog(@"pt:%@",NSStringFromCGPoint(pt));
|
||||
totalX += pt.x;
|
||||
totalY += pt.y;
|
||||
}
|
||||
|
||||
CGFloat averX = totalX / corners.count;
|
||||
CGFloat averY = totalY / corners.count;
|
||||
|
||||
|
||||
|
||||
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
|
||||
|
||||
NSLog(@"averx:%f,avery:%f minsize:%f",averX,averY,minSize);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
[self signCodeWithCenterX:averX centerY:averY];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
- (void)signCodeWithCenterX:(CGFloat)centerX centerY:(CGFloat)centerY
|
||||
{
|
||||
UIView *signView = [[UIView alloc]initWithFrame:CGRectMake(centerX-10, centerY-10, 20, 20)];
|
||||
|
||||
[self.cameraPreView addSubview:signView];
|
||||
signView.backgroundColor = [UIColor redColor];
|
||||
|
||||
self.codeFlagView = signView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//继承者实现
|
||||
- (void)reStartDevice
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)resetCodeFlagView
|
||||
{
|
||||
if (_codeFlagView) {
|
||||
[_codeFlagView removeFromSuperview];
|
||||
self.codeFlagView = nil;
|
||||
}
|
||||
if (self.layers) {
|
||||
|
||||
for (CALayer *layer in self.layers) {
|
||||
[layer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
self.layers = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)imageByCroppingWithSrcImage:(UIImage*)srcImg cropRect:(CGRect)cropRect
|
||||
{
|
||||
|
||||
CGImageRef imageRef = srcImg.CGImage;
|
||||
CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, cropRect);
|
||||
UIImage *cropImage = [UIImage imageWithCGImage:imagePartRef];
|
||||
CGImageRelease(imagePartRef);
|
||||
return cropImage;
|
||||
}
|
||||
|
||||
|
||||
- (void)showNextVCWithScanResult:(LBXScanResult*)strResult
|
||||
{
|
||||
|
||||
if (_continuous) {
|
||||
|
||||
}else
|
||||
{
|
||||
|
||||
ScanResultViewController *vc = [ScanResultViewController new];
|
||||
vc.imgScan = strResult.imgScanned;
|
||||
|
||||
vc.strScan = strResult.strScanned;
|
||||
|
||||
vc.strCodeType = strResult.strBarCodeType;
|
||||
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
|
||||
//隐藏标记条码位置的信息
|
||||
[self resetCodeFlagView];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#pragma mark- 绘制二维码区域标志
|
||||
- (void)didDetectCodes:(CGRect)bounds corner:(NSArray<NSDictionary*>*)corners
|
||||
{
|
||||
AVCaptureVideoPreviewLayer * preview = nil;
|
||||
|
||||
for (CALayer *layer in [self.cameraPreView.layer sublayers]) {
|
||||
|
||||
if ( [layer isKindOfClass:[AVCaptureVideoPreviewLayer class]]) {
|
||||
|
||||
preview = (AVCaptureVideoPreviewLayer*)layer;
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *layers = nil;
|
||||
if (!layers) {
|
||||
layers = @[[self makeBoundsLayer],[self makeCornersLayer]];
|
||||
[preview addSublayer:layers[0]];
|
||||
[preview addSublayer:layers[1]];
|
||||
}
|
||||
|
||||
CAShapeLayer *boundsLayer = layers[0];
|
||||
boundsLayer.path = [self bezierPathForBounds:bounds].CGPath;
|
||||
//得到一个CGPathRef赋给图层的path属性
|
||||
|
||||
if (corners) {
|
||||
CAShapeLayer *cornersLayer = layers[1];
|
||||
cornersLayer.path = [self bezierPathForCorners:corners].CGPath;
|
||||
//对于cornersLayer,基于元数据对象创建一个CGPath
|
||||
}
|
||||
|
||||
self.layers = layers;
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (UIBezierPath *)bezierPathForBounds:(CGRect)bounds {
|
||||
// 图层边界,创建一个和对象的bounds关联的UIBezierPath
|
||||
return [UIBezierPath bezierPathWithRect:bounds];
|
||||
}
|
||||
|
||||
- (CAShapeLayer *)makeBoundsLayer {
|
||||
//CAShapeLayer 是具体化的CALayer子类,用于绘制Bezier路径
|
||||
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
|
||||
shapeLayer.strokeColor = [UIColor colorWithRed:0.96f green:0.75f blue:0.06f alpha:1.0f].CGColor;
|
||||
shapeLayer.fillColor = nil;
|
||||
shapeLayer.lineWidth = 4.0f;
|
||||
|
||||
return shapeLayer;
|
||||
}
|
||||
|
||||
- (CAShapeLayer *)makeCornersLayer {
|
||||
|
||||
CAShapeLayer *cornersLayer = [CAShapeLayer layer];
|
||||
cornersLayer.lineWidth = 2.0f;
|
||||
cornersLayer.strokeColor = [UIColor colorWithRed:0.172 green:0.671 blue:0.428 alpha:1.0].CGColor;
|
||||
cornersLayer.fillColor = [UIColor colorWithRed:0.190 green:0.753 blue:0.489 alpha:0.5].CGColor;
|
||||
|
||||
return cornersLayer;;
|
||||
}
|
||||
|
||||
- (UIBezierPath *)bezierPathForCorners:(NSArray *)corners {
|
||||
|
||||
UIBezierPath *path = [UIBezierPath bezierPath];
|
||||
for (int i = 0; i < corners.count; i ++) {
|
||||
CGPoint point = [self pointForCorner:corners[i]];
|
||||
//遍历每个条目,为每个条目创建一个CGPoint
|
||||
if (i == 0) {
|
||||
[path moveToPoint:point];
|
||||
} else {
|
||||
[path addLineToPoint:point];
|
||||
}
|
||||
}
|
||||
[path closePath];
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark- 相册
|
||||
|
||||
//继承者实现
|
||||
- (void)recognizeImageWithImage:(UIImage*)image
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
|
||||
{
|
||||
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
|
||||
|
||||
if (!image){
|
||||
image = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||
}
|
||||
|
||||
[picker dismissViewControllerAnimated:YES completion:^{
|
||||
[self recognizeImageWithImage:image];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
|
||||
{
|
||||
NSLog(@"cancel");
|
||||
|
||||
[picker dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark- 权限
|
||||
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion
|
||||
{
|
||||
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
|
||||
{
|
||||
AVAuthorizationStatus permission =
|
||||
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
|
||||
switch (permission) {
|
||||
case AVAuthorizationStatusAuthorized:
|
||||
completion(YES);
|
||||
break;
|
||||
case AVAuthorizationStatusDenied:
|
||||
case AVAuthorizationStatusRestricted:
|
||||
completion(NO);
|
||||
break;
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||
completionHandler:^(BOOL granted) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (granted) {
|
||||
completion(true);
|
||||
} else {
|
||||
completion(false);
|
||||
}
|
||||
});
|
||||
|
||||
}];
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+ (void)authorizePhotoPermissionWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
|
||||
{
|
||||
if (@available(iOS 8.0, *)) {
|
||||
|
||||
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
|
||||
|
||||
switch (status) {
|
||||
case PHAuthorizationStatusAuthorized:
|
||||
{
|
||||
if (completion) {
|
||||
completion(YES,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PHAuthorizationStatusRestricted:
|
||||
case PHAuthorizationStatusDenied:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PHAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(status == PHAuthorizationStatusAuthorized,YES);
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
|
||||
switch (status) {
|
||||
case ALAuthorizationStatusAuthorized:
|
||||
{
|
||||
if (completion) {
|
||||
completion(YES, NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ALAuthorizationStatusNotDetermined:
|
||||
{
|
||||
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
|
||||
|
||||
[library enumerateGroupsWithTypes:ALAssetsGroupAll
|
||||
usingBlock:^(ALAssetsGroup *assetGroup, BOOL *stop) {
|
||||
if (*stop) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(YES, NO);
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(NO, YES);
|
||||
});
|
||||
}
|
||||
}];
|
||||
} break;
|
||||
case ALAuthorizationStatusRestricted:
|
||||
case ALAuthorizationStatusDenied:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO, NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isLandScape
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
BOOL landScape = NO;
|
||||
|
||||
|
||||
switch (orientation) {
|
||||
case UIDeviceOrientationPortrait: {
|
||||
landScape = NO;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft: {
|
||||
landScape = YES;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight: {
|
||||
|
||||
landScape = YES;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationPortraitUpsideDown: {
|
||||
|
||||
landScape = NO;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return landScape;
|
||||
|
||||
}
|
||||
|
||||
- (AVCaptureVideoOrientation)videoOrientation
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
|
||||
switch (orientation) {
|
||||
case UIDeviceOrientationPortrait: {
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight : {
|
||||
return AVCaptureVideoOrientationLandscapeLeft;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft: {
|
||||
return AVCaptureVideoOrientationLandscapeRight;
|
||||
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationPortraitUpsideDown: {
|
||||
return AVCaptureVideoOrientationPortraitUpsideDown;
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
break;
|
||||
}
|
||||
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
}
|
||||
|
||||
@end
|
27
Classes_cocos/LBXNative/LBXScanLineAnimation.h
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// LBXScanLineAnimation.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface LBXScanLineAnimation : UIImageView
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开始扫码线动画
|
||||
*
|
||||
* @param animationRect 显示在parentView中得区域
|
||||
* @param parentView 动画显示在UIView
|
||||
* @param image 扫码线的图像
|
||||
*/
|
||||
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView*)parentView Image:(UIImage*)image;
|
||||
|
||||
/**
|
||||
* 停止动画
|
||||
*/
|
||||
- (void)stopAnimating;
|
||||
|
||||
@end
|
155
Classes_cocos/LBXNative/LBXScanLineAnimation.m
Normal file
@ -0,0 +1,155 @@
|
||||
//
|
||||
// LBXScanLineAnimation.m
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanLineAnimation.h"
|
||||
|
||||
|
||||
@interface LBXScanLineAnimation()
|
||||
{
|
||||
int num;
|
||||
BOOL down;
|
||||
NSTimer * timer;
|
||||
|
||||
BOOL isAnimationing;
|
||||
}
|
||||
|
||||
@property (nonatomic,assign) CGRect animationRect;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation LBXScanLineAnimation
|
||||
|
||||
|
||||
|
||||
- (void)stepAnimation
|
||||
{
|
||||
if (!isAnimationing) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CGFloat leftx = _animationRect.origin.x + 5;
|
||||
CGFloat width = _animationRect.size.width - 10;
|
||||
|
||||
self.frame = CGRectMake(leftx, _animationRect.origin.y + 8, width, 8);
|
||||
|
||||
self.alpha = 0.0;
|
||||
|
||||
self.hidden = NO;
|
||||
|
||||
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
self.alpha = 1.0;
|
||||
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
|
||||
}];
|
||||
|
||||
[UIView animateWithDuration:3 animations:^{
|
||||
CGFloat leftx = self.animationRect.origin.x + 5;
|
||||
CGFloat width = self.animationRect.size.width - 10;
|
||||
|
||||
self.frame = CGRectMake(leftx, self.animationRect.origin.y + self.animationRect.size.height - 8, width, 4);
|
||||
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
self.hidden = YES;
|
||||
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView *)parentView Image:(UIImage*)image
|
||||
{
|
||||
if (isAnimationing) {
|
||||
return;
|
||||
}
|
||||
|
||||
isAnimationing = YES;
|
||||
|
||||
|
||||
self.animationRect = animationRect;
|
||||
down = YES;
|
||||
num =0;
|
||||
|
||||
CGFloat centery = CGRectGetMinY(animationRect) + CGRectGetHeight(animationRect)/2;
|
||||
CGFloat leftx = animationRect.origin.x + 5;
|
||||
CGFloat width = animationRect.size.width - 10;
|
||||
|
||||
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
|
||||
self.image = image;
|
||||
|
||||
[parentView addSubview:self];
|
||||
|
||||
[self startAnimating_UIViewAnimation];
|
||||
|
||||
// [self startAnimating_NSTimer];
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)startAnimating_UIViewAnimation
|
||||
{
|
||||
[self stepAnimation];
|
||||
}
|
||||
|
||||
- (void)startAnimating_NSTimer
|
||||
{
|
||||
timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(scanLineAnimation) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
-(void)scanLineAnimation
|
||||
{
|
||||
CGFloat centery = CGRectGetMinY(_animationRect) + CGRectGetHeight(_animationRect)/2;
|
||||
CGFloat leftx = _animationRect.origin.x + 5;
|
||||
CGFloat width = _animationRect.size.width - 10;
|
||||
|
||||
if (down)
|
||||
{
|
||||
num++;
|
||||
|
||||
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
|
||||
|
||||
if (centery+2*num > (CGRectGetMinY(_animationRect) + CGRectGetHeight(_animationRect) - 5 ) )
|
||||
{
|
||||
down = NO;
|
||||
}
|
||||
}
|
||||
else {
|
||||
num --;
|
||||
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
|
||||
if (centery+2*num < (CGRectGetMinY(_animationRect) + 5 ) )
|
||||
{
|
||||
down = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
|
||||
- (void)stopAnimating
|
||||
{
|
||||
if (isAnimationing) {
|
||||
|
||||
isAnimationing = NO;
|
||||
|
||||
if (timer) {
|
||||
[timer invalidate];
|
||||
timer = nil;
|
||||
}
|
||||
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
|
||||
@end
|
48
Classes_cocos/LBXNative/LBXScanNativeViewController.h
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// QQStyleQRScanViewController.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "LBXScanBaseViewController.h"
|
||||
|
||||
|
||||
@interface LBXScanNativeViewController : LBXScanBaseViewController
|
||||
|
||||
|
||||
|
||||
#pragma mark ----- 扫码使用的库对象 -------
|
||||
|
||||
/**
|
||||
@brief 扫码功能封装对象
|
||||
*/
|
||||
@property (nonatomic,strong) LBXScanNative* scanObj;
|
||||
|
||||
|
||||
/*
|
||||
AVMetadataObject.h 头文件中有支持的扫码类型,下面列几个常用的条码
|
||||
AVMetadataObjectTypeQRCode QR二维码
|
||||
AVMetadataObjectTypeCode128Code 支付条码
|
||||
AVMetadataObjectTypeCode93Code 93条码
|
||||
AVMetadataObjectTypeEAN13Code EAN13条码
|
||||
AVMetadataObjectTypeITF14Code native效果比较差,建议ZXing
|
||||
*/
|
||||
//虽然接口是支持可以输入多个码制,但是同时多个效果不理想
|
||||
@property (nonatomic, strong) NSArray<NSString*> *listScanTypes;
|
||||
|
||||
|
||||
//打开相册
|
||||
- (void)openLocalPhoto:(BOOL)allowsEditing;
|
||||
|
||||
//开关闪光灯
|
||||
- (void)openOrCloseFlash;
|
||||
|
||||
|
||||
//关闭扫描
|
||||
- (void)stopScan;
|
||||
|
||||
|
||||
@end
|
282
Classes_cocos/LBXNative/LBXScanNativeViewController.m
Normal file
@ -0,0 +1,282 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanNativeViewController.h"
|
||||
|
||||
|
||||
|
||||
@interface LBXScanNativeViewController ()
|
||||
//@property (nonatomic, strong) UIView *videoView;
|
||||
@end
|
||||
|
||||
@implementation LBXScanNativeViewController
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
|
||||
self.title = [NSString stringWithFormat:@"native 支持横竖屏切换 - %@",self.continuous ? @"连续扫码" : @"不连续扫码"];
|
||||
|
||||
|
||||
|
||||
[self drawScanView];
|
||||
|
||||
[self requestCameraPemissionWithResult:^(BOOL granted) {
|
||||
|
||||
if (granted) {
|
||||
|
||||
[self startScan];
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
|
||||
CGRect rect = self.view.frame;
|
||||
rect.origin = CGPointMake(0, 0);
|
||||
|
||||
self.qRScanView.frame = rect;
|
||||
|
||||
self.cameraPreView.frame = self.view.bounds;
|
||||
|
||||
if (_scanObj) {
|
||||
[_scanObj setVideoLayerframe:self.cameraPreView.frame];
|
||||
}
|
||||
|
||||
[self.qRScanView stopScanAnimation];
|
||||
|
||||
[self.qRScanView startScanAnimation];
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if (!self.firstLoad) {
|
||||
[self reStartDevice];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[self stopScan];
|
||||
|
||||
[self.qRScanView stopScanAnimation];
|
||||
}
|
||||
|
||||
//绘制扫描区域
|
||||
- (void)drawScanView
|
||||
{
|
||||
if (!self.qRScanView)
|
||||
{
|
||||
self.qRScanView = [[LBXScanView alloc]initWithFrame:self.view.bounds style:self.style];
|
||||
|
||||
[self.view insertSubview:self.qRScanView atIndex:1];
|
||||
}
|
||||
|
||||
if (!self.cameraInvokeMsg) {
|
||||
|
||||
self.cameraInvokeMsg = NSLocalizedString(@"wating...", nil);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reStartDevice
|
||||
{
|
||||
[self refreshLandScape];
|
||||
|
||||
[self.qRScanView startDeviceReadyingWithText:self.cameraInvokeMsg];
|
||||
|
||||
_scanObj.orientation = [self videoOrientation];
|
||||
[_scanObj startScan];
|
||||
}
|
||||
|
||||
//启动设备
|
||||
- (void)startScan
|
||||
{
|
||||
if (!self.cameraPreView) {
|
||||
|
||||
CGRect frame = self.view.bounds;
|
||||
|
||||
UIView *videoView = [[UIView alloc]initWithFrame:frame];
|
||||
videoView.backgroundColor = [UIColor clearColor];
|
||||
[self.view insertSubview:videoView atIndex:0];
|
||||
|
||||
self.cameraPreView = videoView;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
if (!_scanObj )
|
||||
{
|
||||
CGRect cropRect = CGRectZero;
|
||||
|
||||
if (self.isOpenInterestRect) {
|
||||
|
||||
//设置只识别框内区域
|
||||
cropRect = [LBXScanView getScanRectWithPreView:self.view style:self.style];
|
||||
}
|
||||
|
||||
|
||||
self.scanObj = [[LBXScanNative alloc]initWithPreView:self.cameraPreView ObjectType:self.listScanTypes cropRect:cropRect videoMaxScale:^(CGFloat maxScale) {
|
||||
[weakSelf setVideoMaxScale:maxScale];
|
||||
|
||||
} success:^(NSArray<LBXScanResult *> *array) {
|
||||
|
||||
[weakSelf handScanNative:array];
|
||||
}];
|
||||
[_scanObj setNeedCaptureImage:self.isNeedScanImage];
|
||||
//是否需要返回条码坐标
|
||||
_scanObj.needCodePosion = YES;
|
||||
_scanObj.continuous = self.continuous;
|
||||
}
|
||||
|
||||
|
||||
_scanObj.onStarted = ^{
|
||||
|
||||
[weakSelf.qRScanView stopDeviceReadying];
|
||||
[weakSelf.qRScanView startScanAnimation];
|
||||
};
|
||||
|
||||
//可动态修改
|
||||
_scanObj.orientation = [self videoOrientation];
|
||||
|
||||
|
||||
[self.qRScanView startDeviceReadyingWithText:self.cameraInvokeMsg];
|
||||
|
||||
|
||||
#if TARGET_OS_SIMULATOR
|
||||
|
||||
#else
|
||||
[_scanObj startScan];
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
- (void)handScanNative:(NSArray<LBXScanResult *> *)array
|
||||
{
|
||||
[self scanResultWithArray:array];
|
||||
}
|
||||
|
||||
- (void)setVideoMaxScale:(CGFloat)maxScale
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)stopScan
|
||||
{
|
||||
[_scanObj stopScan];
|
||||
}
|
||||
|
||||
//开关闪光灯
|
||||
- (void)openOrCloseFlash
|
||||
{
|
||||
[_scanObj changeTorch];
|
||||
|
||||
|
||||
self.isOpenFlash =!self.isOpenFlash;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark- 旋转
|
||||
- (void)refreshLandScape
|
||||
{
|
||||
if ([self isLandScape]) {
|
||||
|
||||
self.style.centerUpOffset = 20;
|
||||
|
||||
CGFloat w = [UIScreen mainScreen].bounds.size.width;
|
||||
CGFloat h = [UIScreen mainScreen].bounds.size.height;
|
||||
|
||||
CGFloat max = MAX(w, h);
|
||||
|
||||
CGFloat min = MIN(w, h);
|
||||
|
||||
CGFloat scanRetangeH = min / 3;
|
||||
|
||||
self.style.xScanRetangleOffset = max / 2 - scanRetangeH / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.style.centerUpOffset = 40;
|
||||
self.style.xScanRetangleOffset = 60;
|
||||
}
|
||||
|
||||
self.qRScanView.viewStyle = self.style;
|
||||
[self.qRScanView setNeedsDisplay];
|
||||
}
|
||||
|
||||
|
||||
- (void)statusBarOrientationChanged:(NSNotification*)notification
|
||||
{
|
||||
[self refreshLandScape];
|
||||
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
|
||||
if (_scanObj) {
|
||||
_scanObj.orientation = [self videoOrientation];
|
||||
}
|
||||
|
||||
[self.qRScanView stopScanAnimation];
|
||||
|
||||
[self.qRScanView startScanAnimation];
|
||||
}
|
||||
|
||||
#pragma mark --打开相册并识别图片
|
||||
|
||||
/*!
|
||||
* 打开本地照片,选择图片识别
|
||||
*/
|
||||
- (void)openLocalPhoto:(BOOL)allowsEditing
|
||||
{
|
||||
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
||||
|
||||
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
|
||||
picker.delegate = self;
|
||||
|
||||
//部分机型有问题
|
||||
picker.allowsEditing = allowsEditing;
|
||||
|
||||
|
||||
[self presentViewController:picker animated:YES completion:nil];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)recognizeImageWithImage:(UIImage*)image
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
if (@available(iOS 8.0, *)) {
|
||||
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
|
||||
[weakSelf scanResultWithArray:array];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
27
Classes_cocos/LBXNative/LBXScanNetAnimation.h
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// LBXScanLineAnimation.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface LBXScanNetAnimation :UIView
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开始扫码网格效果
|
||||
*
|
||||
* @param animationRect 显示在parentView中得区域
|
||||
* @param parentView 动画显示在UIView
|
||||
* @param image 扫码线的图像
|
||||
*/
|
||||
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView*)parentView Image:(UIImage*)image;
|
||||
|
||||
/**
|
||||
* 停止动画
|
||||
*/
|
||||
- (void)stopAnimating;
|
||||
|
||||
@end
|
95
Classes_cocos/LBXNative/LBXScanNetAnimation.m
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// LBXScanLineAnimation.m
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanNetAnimation.h"
|
||||
|
||||
|
||||
@interface LBXScanNetAnimation()
|
||||
{
|
||||
BOOL isAnimationing;
|
||||
}
|
||||
|
||||
@property (nonatomic,assign) CGRect animationRect;
|
||||
@property (nonatomic,strong) UIImageView *scanImageView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LBXScanNetAnimation
|
||||
|
||||
- (instancetype)init{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.clipsToBounds = YES;
|
||||
[self addSubview:self.scanImageView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIImageView *)scanImageView{
|
||||
if (!_scanImageView) {
|
||||
_scanImageView = [[UIImageView alloc] init];
|
||||
}
|
||||
return _scanImageView;
|
||||
}
|
||||
|
||||
- (void)stepAnimation
|
||||
{
|
||||
if (!isAnimationing) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.frame = _animationRect;
|
||||
|
||||
CGFloat scanNetImageViewW = self.frame.size.width;
|
||||
CGFloat scanNetImageH = self.frame.size.height;
|
||||
|
||||
self.alpha = 0.5;
|
||||
_scanImageView.frame = CGRectMake(0, -scanNetImageH, scanNetImageViewW, scanNetImageH);
|
||||
[UIView animateWithDuration:1.4 animations:^{
|
||||
self.alpha = 1.0;
|
||||
|
||||
self.scanImageView.frame = CGRectMake(0, scanNetImageViewW-scanNetImageH, scanNetImageViewW, scanNetImageH);
|
||||
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
|
||||
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
|
||||
}
|
||||
|
||||
|
||||
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView *)parentView Image:(UIImage*)image
|
||||
{
|
||||
[self.scanImageView setImage:image];
|
||||
|
||||
self.animationRect = animationRect;
|
||||
|
||||
[parentView addSubview:self];
|
||||
|
||||
self.hidden = NO;
|
||||
|
||||
isAnimationing = YES;
|
||||
|
||||
[self stepAnimation];
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stopAnimating];
|
||||
}
|
||||
|
||||
- (void)stopAnimating
|
||||
{
|
||||
self.hidden = YES;
|
||||
isAnimationing = NO;
|
||||
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
|
||||
@end
|
19
Classes_cocos/LBXNative/LBXScanVideoZoomView.h
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// LBXScanVideoZoomView.h
|
||||
// testSlider
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LBXScanVideoZoomView : UIView
|
||||
|
||||
/**
|
||||
@brief 控件值变化
|
||||
*/
|
||||
@property (nonatomic, copy,nullable) void (^block)(float value);
|
||||
|
||||
- (void)setMaximunValue:(CGFloat)value;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
126
Classes_cocos/LBXNative/LBXScanVideoZoomView.m
Normal file
@ -0,0 +1,126 @@
|
||||
//
|
||||
// LBXScanVideoZoomView.m
|
||||
// testSlider
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanVideoZoomView.h"
|
||||
|
||||
|
||||
|
||||
@interface LBXScanVideoZoomView()
|
||||
@property (nonatomic, strong) UISlider *slider;
|
||||
@end
|
||||
|
||||
@implementation LBXScanVideoZoomView
|
||||
|
||||
|
||||
// Only override drawRect: if you perform custom drawing.
|
||||
// An empty implementation adversely affects performance during animation.
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
// Drawing code
|
||||
|
||||
UIColor *colorLine = [UIColor whiteColor];
|
||||
|
||||
|
||||
CGColorRef color = colorLine.CGColor;
|
||||
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
||||
CGContextSetStrokeColorWithColor(ctx, color);
|
||||
CGContextSetLineWidth(ctx, 2.0);
|
||||
|
||||
|
||||
CGFloat borderDiff = 20;
|
||||
CGFloat w = borderDiff/2;
|
||||
CGFloat diff = 5;
|
||||
//左边减号
|
||||
CGContextMoveToPoint(ctx, diff, CGRectGetHeight(self.frame)/2);
|
||||
CGContextAddLineToPoint(ctx, diff + w, CGRectGetHeight(self.frame)/2);
|
||||
|
||||
//右边加号
|
||||
//横
|
||||
CGFloat rx = CGRectGetWidth(self.frame) - borderDiff + diff;
|
||||
CGContextMoveToPoint(ctx, rx, CGRectGetHeight(self.frame)/2);
|
||||
CGContextAddLineToPoint(ctx, rx + w, CGRectGetHeight(self.frame)/2);
|
||||
|
||||
//竖
|
||||
CGFloat hDiff = CGRectGetHeight(self.frame)/2 - w/2;
|
||||
CGContextMoveToPoint(ctx, rx+w/2 , hDiff);
|
||||
CGContextAddLineToPoint(ctx, rx+w/2, CGRectGetHeight(self.frame)-hDiff);
|
||||
|
||||
|
||||
CGContextStrokePath(ctx);
|
||||
}
|
||||
|
||||
- (UIImage *) toImage:(UIColor*)color size:(CGSize)size
|
||||
{
|
||||
CGRect rect=CGRectMake(0.0f, 0.0f, size.width, size.height);
|
||||
UIGraphicsBeginImageContext(rect.size);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetFillColorWithColor(context, [color CGColor]);
|
||||
CGContextFillRect(context, rect);
|
||||
|
||||
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return theImage;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
}
|
||||
|
||||
self.backgroundColor = [UIColor colorWithRed:10 green:10 blue:10 alpha:0.2];
|
||||
[self.slider setThumbImage:[self toImage:[UIColor whiteColor] size:CGSizeMake(3, 12)] forState:UIControlStateNormal];
|
||||
self.slider.minimumTrackTintColor = [UIColor whiteColor];
|
||||
self.slider.maximumTrackTintColor = [UIColor colorWithRed:146/255.0 green:146/255.0 blue:146/255.0 alpha:1.0];
|
||||
[self.slider addTarget:self action:@selector(sliderValueChange) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
self.layer.masksToBounds = YES;
|
||||
self.layer.cornerRadius = 8.0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)sliderValueChange
|
||||
{
|
||||
NSLog(@"%f",self.slider.value);
|
||||
|
||||
if (_block) {
|
||||
_block(self.slider.value);
|
||||
}
|
||||
}
|
||||
|
||||
//- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
|
||||
|
||||
- (UISlider*)slider
|
||||
{
|
||||
if (!_slider) {
|
||||
|
||||
_slider = [[UISlider alloc]init];
|
||||
[self addSubview:_slider];
|
||||
_slider.minimumValue = 1.0;
|
||||
_slider.maximumValue = 50.0;
|
||||
}
|
||||
return _slider;
|
||||
}
|
||||
|
||||
- (void)setMaximunValue:(CGFloat)value
|
||||
{
|
||||
self.slider.maximumValue = value;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
CGFloat borderDiff = 20;
|
||||
|
||||
_slider.bounds = CGRectMake(0, 0, CGRectGetWidth(self.frame)-borderDiff*2, CGRectGetHeight(self.frame));
|
||||
_slider.center = CGPointMake(CGRectGetWidth(self.frame)/2, CGRectGetHeight(self.frame)/2);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
73
Classes_cocos/LBXNative/LBXScanView.h
Normal file
@ -0,0 +1,73 @@
|
||||
//
|
||||
// LBXScanView.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "LBXScanLineAnimation.h"
|
||||
#import "LBXScanNetAnimation.h"
|
||||
#import "LBXScanViewStyle.h"
|
||||
|
||||
#define LBXScan_Define_UI
|
||||
|
||||
/**
|
||||
扫码区域显示效果
|
||||
*/
|
||||
@interface LBXScanView : UIView
|
||||
|
||||
//扫码区域各种参数
|
||||
@property (nonatomic, strong) LBXScanViewStyle* viewStyle;
|
||||
/**
|
||||
@brief 初始化
|
||||
@param frame 位置大小
|
||||
@param style 类型
|
||||
|
||||
@return instancetype
|
||||
*/
|
||||
-(id)initWithFrame:(CGRect)frame style:(LBXScanViewStyle*)style;
|
||||
|
||||
/**
|
||||
* 设备启动中文字提示
|
||||
*/
|
||||
- (void)startDeviceReadyingWithText:(NSString*)text;
|
||||
|
||||
/**
|
||||
* 设备启动完成
|
||||
*/
|
||||
- (void)stopDeviceReadying;
|
||||
|
||||
/**
|
||||
* 开始扫描动画
|
||||
*/
|
||||
- (void)startScanAnimation;
|
||||
|
||||
/**
|
||||
* 结束扫描动画
|
||||
*/
|
||||
- (void)stopScanAnimation;
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
@brief 根据矩形区域,获取Native扫码识别兴趣区域
|
||||
@param view 视频流显示UIView
|
||||
@param style 效果界面参数
|
||||
@return 识别区域
|
||||
*/
|
||||
+ (CGRect)getScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
根据矩形区域,获取ZXing库扫码识别兴趣区域
|
||||
|
||||
@param view 视频流显示视图
|
||||
@param style 效果界面参数
|
||||
@return 识别区域
|
||||
*/
|
||||
+ (CGRect)getZXingScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style;
|
||||
|
||||
|
||||
@end
|
519
Classes_cocos/LBXNative/LBXScanView.m
Normal file
@ -0,0 +1,519 @@
|
||||
|
||||
//
|
||||
// LBXScanView.m
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanView.h"
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LBXScanView()
|
||||
|
||||
|
||||
|
||||
|
||||
//扫码区域
|
||||
@property (nonatomic,assign)CGRect scanRetangleRect;
|
||||
|
||||
//线条扫码动画封装
|
||||
@property (nonatomic,strong,nullable)LBXScanLineAnimation *scanLineAnimation;
|
||||
//网格扫码动画封装
|
||||
@property (nonatomic,strong,nullable)LBXScanNetAnimation *scanNetAnimation;
|
||||
|
||||
//线条在中间位置,不移动
|
||||
@property (nonatomic,strong,nullable)UIImageView *scanLineStill;
|
||||
|
||||
/**
|
||||
@brief 启动相机时 菊花等待
|
||||
*/
|
||||
@property(nonatomic,strong,nullable)UIActivityIndicatorView* activityView;
|
||||
|
||||
/**
|
||||
@brief 启动相机中的提示文字
|
||||
*/
|
||||
@property(nonatomic,strong,nullable)UILabel *labelReadying;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@implementation LBXScanView
|
||||
|
||||
|
||||
-(id)initWithFrame:(CGRect)frame style:(LBXScanViewStyle*)style
|
||||
{
|
||||
if (self = [super initWithFrame:frame])
|
||||
{
|
||||
self.viewStyle = style;
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
[self drawScanRect];
|
||||
}
|
||||
- (void)startDeviceReadyingWithText:(NSString*)text
|
||||
{
|
||||
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
if (!_viewStyle.isNeedShowRetangle) {
|
||||
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / _viewStyle.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
|
||||
|
||||
//设备启动状态提示
|
||||
if (!_activityView)
|
||||
{
|
||||
self.activityView = [[UIActivityIndicatorView alloc]init];
|
||||
|
||||
[_activityView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
|
||||
|
||||
self.labelReadying = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, sizeRetangle.width, 30)];
|
||||
_labelReadying.backgroundColor = [UIColor clearColor];
|
||||
_labelReadying.textColor = [UIColor whiteColor];
|
||||
_labelReadying.font = [UIFont systemFontOfSize:18.];
|
||||
_labelReadying.text = text;
|
||||
[_labelReadying sizeToFit];
|
||||
CGRect frame = _labelReadying.frame;
|
||||
CGPoint centerPt = CGPointMake(self.frame.size.width/2 + 20, YMinRetangle + sizeRetangle.height/2);
|
||||
_labelReadying.bounds = CGRectMake(0, 0, frame.size.width,30);
|
||||
_labelReadying.center = centerPt;
|
||||
|
||||
_activityView.bounds = CGRectMake(0, 0, 30, 30);
|
||||
if (text)
|
||||
_activityView.center = CGPointMake(centerPt.x - frame.size.width/2 - 24 , _labelReadying.center.y);
|
||||
else
|
||||
_activityView.center = CGPointMake(self.frame.size.width/2 , _labelReadying.center.y);
|
||||
|
||||
[self addSubview:_activityView];
|
||||
[self addSubview:_labelReadying];
|
||||
[_activityView startAnimating];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
if (_labelReadying && _activityView) {
|
||||
|
||||
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
|
||||
|
||||
CGRect frame = _labelReadying.frame;
|
||||
CGPoint centerPt = CGPointMake(self.frame.size.width/2 + 20, YMinRetangle + sizeRetangle.height/2);
|
||||
_labelReadying.bounds = CGRectMake(0, 0, frame.size.width,30);
|
||||
_labelReadying.center = centerPt;
|
||||
|
||||
|
||||
_activityView.bounds = CGRectMake(0, 0, 30, 30);
|
||||
if (_labelReadying.text)
|
||||
_activityView.center = CGPointMake(centerPt.x - frame.size.width/2 - 24 , _labelReadying.center.y);
|
||||
else
|
||||
_activityView.center = CGPointMake(self.frame.size.width/2 , _labelReadying.center.y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)stopDeviceReadying
|
||||
{
|
||||
if (_activityView) {
|
||||
|
||||
[_activityView stopAnimating];
|
||||
[_activityView removeFromSuperview];
|
||||
[_labelReadying removeFromSuperview];
|
||||
|
||||
self.activityView = nil;
|
||||
self.labelReadying = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始扫描动画
|
||||
*/
|
||||
- (void)startScanAnimation
|
||||
{
|
||||
|
||||
[self refreshScanRetangleRect];
|
||||
|
||||
switch (_viewStyle.anmiationStyle)
|
||||
{
|
||||
case LBXScanViewAnimationStyle_LineMove:
|
||||
{
|
||||
//线动画
|
||||
if (!_scanLineAnimation)
|
||||
self.scanLineAnimation = [[LBXScanLineAnimation alloc]init];
|
||||
[_scanLineAnimation startAnimatingWithRect:_scanRetangleRect
|
||||
InView:self
|
||||
Image:_viewStyle.animationImage];
|
||||
}
|
||||
break;
|
||||
case LBXScanViewAnimationStyle_NetGrid:
|
||||
{
|
||||
//网格动画
|
||||
if (!_scanNetAnimation)
|
||||
self.scanNetAnimation = [[LBXScanNetAnimation alloc]init];
|
||||
[_scanNetAnimation startAnimatingWithRect:_scanRetangleRect
|
||||
InView:self
|
||||
Image:_viewStyle.animationImage];
|
||||
}
|
||||
break;
|
||||
case LBXScanViewAnimationStyle_LineStill:
|
||||
{
|
||||
if (!_scanLineStill) {
|
||||
|
||||
CGRect stillRect = CGRectMake(_scanRetangleRect.origin.x+20,
|
||||
_scanRetangleRect.origin.y + _scanRetangleRect.size.height/2,
|
||||
_scanRetangleRect.size.width-40,
|
||||
2);
|
||||
_scanLineStill = [[UIImageView alloc]initWithFrame:stillRect];
|
||||
_scanLineStill.image = _viewStyle.animationImage;
|
||||
}
|
||||
[self addSubview:_scanLineStill];
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 结束扫描动画
|
||||
*/
|
||||
- (void)stopScanAnimation
|
||||
{
|
||||
if (_scanLineAnimation) {
|
||||
[_scanLineAnimation stopAnimating];
|
||||
self.scanLineAnimation = nil;
|
||||
}
|
||||
|
||||
if (_scanNetAnimation) {
|
||||
[_scanNetAnimation stopAnimating];
|
||||
self.scanNetAnimation = nil;
|
||||
}
|
||||
|
||||
if (_scanLineStill) {
|
||||
[_scanLineStill removeFromSuperview];
|
||||
self.scanLineStill = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)refreshScanRetangleRect
|
||||
{
|
||||
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
//if (!_viewStyle.isScanRetangelSquare)
|
||||
if (_viewStyle.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / _viewStyle.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
|
||||
// CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
|
||||
// CGFloat XRetangleRight = self.frame.size.width - XRetangleLeft;
|
||||
|
||||
_scanRetangleRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
|
||||
|
||||
}
|
||||
|
||||
- (void)drawScanRect
|
||||
{
|
||||
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
//if (!_viewStyle.isScanRetangelSquare)
|
||||
if (_viewStyle.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / _viewStyle.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
|
||||
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
|
||||
CGFloat XRetangleRight = self.frame.size.width - XRetangleLeft;
|
||||
|
||||
|
||||
|
||||
NSLog(@"frame:%@",NSStringFromCGRect(self.frame));
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
|
||||
//非扫码区域半透明
|
||||
{
|
||||
//设置非识别区域颜色
|
||||
|
||||
const CGFloat *components = CGColorGetComponents(_viewStyle.notRecoginitonArea.CGColor);
|
||||
|
||||
|
||||
CGFloat red_notRecoginitonArea = components[0];
|
||||
CGFloat green_notRecoginitonArea = components[1];
|
||||
CGFloat blue_notRecoginitonArea = components[2];
|
||||
CGFloat alpa_notRecoginitonArea = components[3];
|
||||
|
||||
|
||||
CGContextSetRGBFillColor(context, red_notRecoginitonArea, green_notRecoginitonArea,
|
||||
blue_notRecoginitonArea, alpa_notRecoginitonArea);
|
||||
|
||||
//填充矩形
|
||||
|
||||
//扫码区域上面填充
|
||||
CGRect rect = CGRectMake(0, 0, self.frame.size.width, YMinRetangle);
|
||||
CGContextFillRect(context, rect);
|
||||
|
||||
|
||||
//扫码区域左边填充
|
||||
rect = CGRectMake(0, YMinRetangle, XRetangleLeft,sizeRetangle.height);
|
||||
CGContextFillRect(context, rect);
|
||||
|
||||
//扫码区域右边填充
|
||||
rect = CGRectMake(XRetangleRight, YMinRetangle, XRetangleLeft,sizeRetangle.height);
|
||||
CGContextFillRect(context, rect);
|
||||
|
||||
//扫码区域下面填充
|
||||
rect = CGRectMake(0, YMaxRetangle, self.frame.size.width,self.frame.size.height - YMaxRetangle);
|
||||
CGContextFillRect(context, rect);
|
||||
//执行绘画
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
if (_viewStyle.isNeedShowRetangle)
|
||||
{
|
||||
//中间画矩形(正方形)
|
||||
CGContextSetStrokeColorWithColor(context, _viewStyle.colorRetangleLine.CGColor);
|
||||
CGContextSetLineWidth(context, 1);
|
||||
|
||||
CGContextAddRect(context, CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height));
|
||||
|
||||
//CGContextMoveToPoint(context, XRetangleLeft, YMinRetangle);
|
||||
//CGContextAddLineToPoint(context, XRetangleLeft+sizeRetangle.width, YMinRetangle);
|
||||
|
||||
CGContextStrokePath(context);
|
||||
|
||||
}
|
||||
_scanRetangleRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
|
||||
|
||||
|
||||
//画矩形框4格外围相框角
|
||||
|
||||
//相框角的宽度和高度
|
||||
int wAngle = _viewStyle.photoframeAngleW;
|
||||
int hAngle = _viewStyle.photoframeAngleH;
|
||||
|
||||
//4个角的 线的宽度
|
||||
CGFloat linewidthAngle = _viewStyle.photoframeLineW;// 经验参数:6和4
|
||||
|
||||
//画扫码矩形以及周边半透明黑色坐标参数
|
||||
CGFloat diffAngle = 0.0f;
|
||||
//diffAngle = linewidthAngle / 2; //框外面4个角,与框有缝隙
|
||||
//diffAngle = linewidthAngle/2; //框4个角 在线上加4个角效果
|
||||
//diffAngle = 0;//与矩形框重合
|
||||
|
||||
switch (_viewStyle.photoframeAngleStyle)
|
||||
{
|
||||
case LBXScanViewPhotoframeAngleStyle_Outer:
|
||||
{
|
||||
diffAngle = linewidthAngle/3;//框外面4个角,与框紧密联系在一起
|
||||
}
|
||||
break;
|
||||
case LBXScanViewPhotoframeAngleStyle_On:
|
||||
{
|
||||
diffAngle = 0;
|
||||
}
|
||||
break;
|
||||
case LBXScanViewPhotoframeAngleStyle_Inner:
|
||||
{
|
||||
diffAngle = -_viewStyle.photoframeLineW/2;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
diffAngle = linewidthAngle/3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
CGContextSetStrokeColorWithColor(context, _viewStyle.colorAngle.CGColor);
|
||||
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
// Draw them with a 2.0 stroke width so they are a bit more visible.
|
||||
CGContextSetLineWidth(context, linewidthAngle);
|
||||
|
||||
|
||||
//
|
||||
CGFloat leftX = XRetangleLeft - diffAngle;
|
||||
CGFloat topY = YMinRetangle - diffAngle;
|
||||
CGFloat rightX = XRetangleRight + diffAngle;
|
||||
CGFloat bottomY = YMaxRetangle + diffAngle;
|
||||
|
||||
//左上角水平线
|
||||
CGContextMoveToPoint(context, leftX-linewidthAngle/2, topY);
|
||||
CGContextAddLineToPoint(context, leftX + wAngle, topY);
|
||||
|
||||
//左上角垂直线
|
||||
CGContextMoveToPoint(context, leftX, topY-linewidthAngle/2);
|
||||
CGContextAddLineToPoint(context, leftX, topY+hAngle);
|
||||
|
||||
|
||||
//左下角水平线
|
||||
CGContextMoveToPoint(context, leftX-linewidthAngle/2, bottomY);
|
||||
CGContextAddLineToPoint(context, leftX + wAngle, bottomY);
|
||||
|
||||
//左下角垂直线
|
||||
CGContextMoveToPoint(context, leftX, bottomY+linewidthAngle/2);
|
||||
CGContextAddLineToPoint(context, leftX, bottomY - hAngle);
|
||||
|
||||
|
||||
//右上角水平线
|
||||
CGContextMoveToPoint(context, rightX+linewidthAngle/2, topY);
|
||||
CGContextAddLineToPoint(context, rightX - wAngle, topY);
|
||||
|
||||
//右上角垂直线
|
||||
CGContextMoveToPoint(context, rightX, topY-linewidthAngle/2);
|
||||
CGContextAddLineToPoint(context, rightX, topY + hAngle);
|
||||
|
||||
|
||||
//右下角水平线
|
||||
CGContextMoveToPoint(context, rightX+linewidthAngle/2, bottomY);
|
||||
CGContextAddLineToPoint(context, rightX - wAngle, bottomY);
|
||||
|
||||
//右下角垂直线
|
||||
CGContextMoveToPoint(context, rightX, bottomY+linewidthAngle/2);
|
||||
CGContextAddLineToPoint(context, rightX, bottomY - hAngle);
|
||||
|
||||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//根据矩形区域,获取识别区域
|
||||
+ (CGRect)getScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style
|
||||
{
|
||||
int XRetangleLeft = style.xScanRetangleOffset;
|
||||
CGSize sizeRetangle = CGSizeMake(view.frame.size.width - XRetangleLeft*2, view.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
if (style.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / style.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = view.frame.size.height / 2.0 - sizeRetangle.height/2.0 - style.centerUpOffset;
|
||||
//扫码区域坐标
|
||||
CGRect cropRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
|
||||
|
||||
|
||||
//计算兴趣区域
|
||||
CGRect rectOfInterest;
|
||||
|
||||
//ref:http://www.cocoachina.com/ios/20141225/10763.html
|
||||
CGSize size = view.bounds.size;
|
||||
CGFloat p1 = size.height/size.width;
|
||||
CGFloat p2 = 1920./1080.; //使用了1080p的图像输出
|
||||
if (p1 < p2) {
|
||||
CGFloat fixHeight = size.width * 1920. / 1080.;
|
||||
CGFloat fixPadding = (fixHeight - size.height)/2;
|
||||
rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
|
||||
cropRect.origin.x/size.width,
|
||||
cropRect.size.height/fixHeight,
|
||||
cropRect.size.width/size.width);
|
||||
|
||||
|
||||
} else {
|
||||
CGFloat fixWidth = size.height * 1080. / 1920.;
|
||||
CGFloat fixPadding = (fixWidth - size.width)/2;
|
||||
rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
|
||||
(cropRect.origin.x + fixPadding)/fixWidth,
|
||||
cropRect.size.height/size.height,
|
||||
cropRect.size.width/fixWidth);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return rectOfInterest;
|
||||
}
|
||||
|
||||
//根据矩形区域,获取识别区域
|
||||
+ (CGRect)getZXingScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style
|
||||
{
|
||||
int XRetangleLeft = style.xScanRetangleOffset;
|
||||
CGSize sizeRetangle = CGSizeMake(view.frame.size.width - XRetangleLeft*2, view.frame.size.width - XRetangleLeft*2);
|
||||
|
||||
if (style.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / style.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = view.frame.size.height / 2.0 - sizeRetangle.height/2.0 - style.centerUpOffset;
|
||||
|
||||
XRetangleLeft = XRetangleLeft/view.frame.size.width * 1080;
|
||||
YMinRetangle = YMinRetangle / view.frame.size.height * 1920;
|
||||
CGFloat width = sizeRetangle.width / view.frame.size.width * 1080;
|
||||
CGFloat height = sizeRetangle.height / view.frame.size.height * 1920;
|
||||
|
||||
//扫码区域坐标
|
||||
CGRect cropRect = CGRectMake(XRetangleLeft, YMinRetangle, width,height);
|
||||
|
||||
return cropRect;
|
||||
}
|
||||
|
||||
|
||||
@end
|
174
Classes_cocos/LBXNative/LBXScanViewController.h
Normal file
@ -0,0 +1,174 @@
|
||||
//
|
||||
// QQStyleQRScanViewController.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LBXScanTypes.h"
|
||||
|
||||
//UI
|
||||
#ifdef LBXScan_Define_UI
|
||||
#import "LBXScanView.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LBXScan_Define_Native
|
||||
#import "LBXScanNative.h" //原生扫码封装
|
||||
#endif
|
||||
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
#import "ZXingWrapper.h" //ZXing扫码封装
|
||||
#endif
|
||||
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
#import "ZBarSDK.h"
|
||||
#import "LBXZBarWrapper.h"//ZBar扫码封装
|
||||
#endif
|
||||
|
||||
|
||||
typedef NS_ENUM(NSInteger, SCANLIBRARYTYPE) {
|
||||
SLT_Native,
|
||||
SLT_ZXing,
|
||||
SLT_ZBar
|
||||
};
|
||||
|
||||
// @[@"QRCode",@"BarCode93",@"BarCode128",@"BarCodeITF",@"EAN13"];
|
||||
typedef NS_ENUM(NSInteger, SCANCODETYPE) {
|
||||
SCT_QRCode, //QR二维码
|
||||
SCT_BarCode93,
|
||||
SCT_BarCode128,//支付条形码(支付宝、微信支付条形码)
|
||||
SCT_BarCodeITF,//燃气回执联 条形码?
|
||||
SCT_BarEAN13 //一般用做商品码
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
扫码结果delegate,也可通过继承本控制器,override方法scanResultWithArray即可
|
||||
*/
|
||||
@protocol LBXScanViewControllerDelegate <NSObject>
|
||||
@optional
|
||||
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array;
|
||||
@end
|
||||
|
||||
|
||||
@interface LBXScanViewController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
|
||||
|
||||
|
||||
#pragma mark ---- 需要初始化参数 ------
|
||||
//当前选择的扫码库
|
||||
@property (nonatomic, assign) SCANLIBRARYTYPE libraryType;
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
当前选择的识别码制
|
||||
- ZXing暂不支持类型选择
|
||||
*/
|
||||
@property (nonatomic, assign) SCANCODETYPE scanCodeType;
|
||||
|
||||
|
||||
|
||||
//扫码结果委托,另外一种方案是通过继承本控制器,override方法scanResultWithArray即可
|
||||
@property (nonatomic, weak) id<LBXScanViewControllerDelegate> delegate;
|
||||
|
||||
|
||||
/**
|
||||
@brief 是否需要扫码图像
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isNeedScanImage;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief 启动区域识别功能,ZBar暂不支持
|
||||
*/
|
||||
@property(nonatomic,assign) BOOL isOpenInterestRect;
|
||||
|
||||
|
||||
/**
|
||||
相机启动提示,如 相机启动中...
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *cameraInvokeMsg;
|
||||
|
||||
/**
|
||||
* 界面效果参数
|
||||
*/
|
||||
#ifdef LBXScan_Define_UI
|
||||
@property (nonatomic, strong) LBXScanViewStyle *style;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#pragma mark ----- 扫码使用的库对象 -------
|
||||
|
||||
#ifdef LBXScan_Define_Native
|
||||
/**
|
||||
@brief 扫码功能封装对象
|
||||
*/
|
||||
@property (nonatomic,strong) LBXScanNative* scanObj;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
/**
|
||||
ZXing扫码对象
|
||||
*/
|
||||
@property (nonatomic, strong) ZXingWrapper *zxingObj;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
/**
|
||||
ZBar扫码对象
|
||||
*/
|
||||
@property (nonatomic, strong) LBXZBarWrapper *zbarObj;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - 扫码界面效果及提示等
|
||||
/**
|
||||
@brief 扫码区域视图,二维码一般都是框
|
||||
*/
|
||||
|
||||
#ifdef LBXScan_Define_UI
|
||||
@property (nonatomic,strong) LBXScanView* qRScanView;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief 扫码存储的当前图片
|
||||
*/
|
||||
@property(nonatomic,strong) UIImage* scanImage;
|
||||
|
||||
|
||||
/**
|
||||
@brief 闪关灯开启状态记录
|
||||
*/
|
||||
@property(nonatomic,assign)BOOL isOpenFlash;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//打开相册
|
||||
- (void)openLocalPhoto:(BOOL)allowsEditing;
|
||||
|
||||
//开关闪光灯
|
||||
- (void)openOrCloseFlash;
|
||||
|
||||
//启动扫描
|
||||
- (void)reStartDevice;
|
||||
|
||||
//关闭扫描
|
||||
- (void)stopScan;
|
||||
|
||||
|
||||
@end
|
596
Classes_cocos/LBXNative/LBXScanViewController.m
Normal file
@ -0,0 +1,596 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#import "LBXScanViewController.h"
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <Photos/Photos.h>
|
||||
|
||||
@interface LBXScanViewController ()
|
||||
@end
|
||||
|
||||
@implementation LBXScanViewController
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
|
||||
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
self.title = @"native";
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
self.title = @"ZXing";
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
self.title = @"ZBar";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
[self drawScanView];
|
||||
|
||||
[self requestCameraPemissionWithResult:^(BOOL granted) {
|
||||
|
||||
if (granted) {
|
||||
|
||||
//不延时,可能会导致界面黑屏并卡住一会
|
||||
[self performSelector:@selector(startScan) withObject:nil afterDelay:0.3];
|
||||
|
||||
}else{
|
||||
|
||||
#ifdef LBXScan_Define_UI
|
||||
[self.qRScanView stopDeviceReadying];
|
||||
#endif
|
||||
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
//绘制扫描区域
|
||||
- (void)drawScanView
|
||||
{
|
||||
#ifdef LBXScan_Define_UI
|
||||
|
||||
if (!_qRScanView)
|
||||
{
|
||||
CGRect rect = self.view.frame;
|
||||
rect.origin = CGPointMake(0, 0);
|
||||
|
||||
self.qRScanView = [[LBXScanView alloc]initWithFrame:rect style:_style];
|
||||
|
||||
[self.view addSubview:_qRScanView];
|
||||
}
|
||||
|
||||
if (!_cameraInvokeMsg) {
|
||||
|
||||
// _cameraInvokeMsg = NSLocalizedString(@"wating...", nil);
|
||||
}
|
||||
|
||||
[_qRScanView startDeviceReadyingWithText:_cameraInvokeMsg];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)reStartDevice
|
||||
{
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
{
|
||||
#ifdef LBXScan_Define_Native
|
||||
[_scanObj startScan];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
[_zxingObj start];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
[_zbarObj start];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//启动设备
|
||||
- (void)startScan
|
||||
{
|
||||
UIView *videoView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))];
|
||||
videoView.backgroundColor = [UIColor clearColor];
|
||||
[self.view insertSubview:videoView atIndex:0];
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
{
|
||||
|
||||
|
||||
#ifdef LBXScan_Define_Native
|
||||
|
||||
if (!_scanObj )
|
||||
{
|
||||
CGRect cropRect = CGRectZero;
|
||||
|
||||
if (_isOpenInterestRect) {
|
||||
|
||||
//设置只识别框内区域
|
||||
cropRect = [LBXScanView getScanRectWithPreView:self.view style:_style];
|
||||
}
|
||||
|
||||
NSString *strCode = AVMetadataObjectTypeQRCode;
|
||||
if (_scanCodeType != SCT_BarCodeITF ) {
|
||||
|
||||
strCode = [self nativeCodeWithType:_scanCodeType];
|
||||
}
|
||||
|
||||
//AVMetadataObjectTypeITF14Code 扫码效果不行,另外只能输入一个码制,虽然接口是可以输入多个码制
|
||||
self.scanObj = [[LBXScanNative alloc]initWithPreView:videoView ObjectType:@[strCode] cropRect:cropRect success:^(NSArray<LBXScanResult *> *array) {
|
||||
|
||||
[weakSelf scanResultWithArray:array];
|
||||
}];
|
||||
[_scanObj setNeedCaptureImage:_isNeedScanImage];
|
||||
}
|
||||
[_scanObj startScan];
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
{
|
||||
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
if (!_zxingObj) {
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
self.zxingObj = [[ZXingWrapper alloc]initWithPreView:videoView block:^(ZXBarcodeFormat barcodeFormat, NSString *str, UIImage *scanImg) {
|
||||
|
||||
LBXScanResult *result = [[LBXScanResult alloc]init];
|
||||
result.strScanned = str;
|
||||
result.imgScanned = scanImg;
|
||||
result.strBarCodeType = [weakSelf convertZXBarcodeFormat:barcodeFormat];
|
||||
|
||||
[weakSelf scanResultWithArray:@[result]];
|
||||
|
||||
}];
|
||||
|
||||
if (_isOpenInterestRect) {
|
||||
|
||||
//设置只识别框内区域
|
||||
CGRect cropRect = [LBXScanView getZXingScanRectWithPreView:videoView style:_style];
|
||||
|
||||
[_zxingObj setScanRect:cropRect];
|
||||
}
|
||||
}
|
||||
[_zxingObj start];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
if (!_zbarObj) {
|
||||
|
||||
self.zbarObj = [[LBXZBarWrapper alloc]initWithPreView:videoView barCodeType:[self zbarTypeWithScanType:_scanCodeType] block:^(NSArray<LBXZbarResult *> *result) {
|
||||
|
||||
//测试,只使用扫码结果第一项
|
||||
LBXZbarResult *firstObj = result[0];
|
||||
|
||||
LBXScanResult *scanResult = [[LBXScanResult alloc]init];
|
||||
scanResult.strScanned = firstObj.strScanned;
|
||||
scanResult.imgScanned = firstObj.imgScanned;
|
||||
scanResult.strBarCodeType = [LBXZBarWrapper convertFormat2String:firstObj.format];
|
||||
|
||||
[weakSelf scanResultWithArray:@[scanResult]];
|
||||
}];
|
||||
}
|
||||
[_zbarObj start];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef LBXScan_Define_UI
|
||||
[_qRScanView stopDeviceReadying];
|
||||
[_qRScanView startScanAnimation];
|
||||
#endif
|
||||
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
}
|
||||
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
- (zbar_symbol_type_t)zbarTypeWithScanType:(SCANCODETYPE)type
|
||||
{
|
||||
//test only ZBAR_I25 effective,why
|
||||
return ZBAR_I25;
|
||||
|
||||
// switch (type) {
|
||||
// case SCT_QRCode:
|
||||
// return ZBAR_QRCODE;
|
||||
// break;
|
||||
// case SCT_BarCode93:
|
||||
// return ZBAR_CODE93;
|
||||
// break;
|
||||
// case SCT_BarCode128:
|
||||
// return ZBAR_CODE128;
|
||||
// break;
|
||||
// case SCT_BarEAN13:
|
||||
// return ZBAR_EAN13;
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return (zbar_symbol_type_t)type;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
|
||||
[self stopScan];
|
||||
|
||||
#ifdef LBXScan_Define_UI
|
||||
[_qRScanView stopScanAnimation];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)stopScan
|
||||
{
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
{
|
||||
#ifdef LBXScan_Define_Native
|
||||
[_scanObj stopScan];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
[_zxingObj stop];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
[_zbarObj stop];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -扫码结果处理
|
||||
|
||||
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
|
||||
{
|
||||
//设置了委托的处理
|
||||
if (_delegate && array && array.count > 0) {
|
||||
[_delegate scanResultWithArray:array];
|
||||
}
|
||||
|
||||
//也可以通过继承LBXScanViewController,重写本方法即可
|
||||
}
|
||||
|
||||
|
||||
|
||||
//开关闪光灯
|
||||
- (void)openOrCloseFlash
|
||||
{
|
||||
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
{
|
||||
#ifdef LBXScan_Define_Native
|
||||
[_scanObj changeTorch];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
[_zxingObj openOrCloseTorch];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
[_zbarObj openOrCloseFlash];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
self.isOpenFlash =!self.isOpenFlash;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark --打开相册并识别图片
|
||||
|
||||
/*!
|
||||
* 打开本地照片,选择图片识别
|
||||
*/
|
||||
- (void)openLocalPhoto:(BOOL)allowsEditing
|
||||
{
|
||||
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
||||
|
||||
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
|
||||
picker.delegate = self;
|
||||
|
||||
//部分机型有问题
|
||||
picker.allowsEditing = allowsEditing;
|
||||
|
||||
|
||||
[self presentViewController:picker animated:YES completion:nil];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//当选择一张图片后进入这里
|
||||
|
||||
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
|
||||
{
|
||||
[picker dismissViewControllerAnimated:YES completion:nil];
|
||||
|
||||
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
|
||||
|
||||
if (!image){
|
||||
image = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
switch (_libraryType) {
|
||||
case SLT_Native:
|
||||
{
|
||||
#ifdef LBXScan_Define_Native
|
||||
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 8.0)
|
||||
{
|
||||
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
|
||||
[weakSelf scanResultWithArray:array];
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self showError:@"native低于ios8.0系统不支持识别图片条码"];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SLT_ZXing:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
|
||||
[ZXingWrapper recognizeImage:image block:^(ZXBarcodeFormat barcodeFormat, NSString *str) {
|
||||
|
||||
LBXScanResult *result = [[LBXScanResult alloc]init];
|
||||
result.strScanned = str;
|
||||
result.imgScanned = image;
|
||||
result.strBarCodeType = [self convertZXBarcodeFormat:barcodeFormat];
|
||||
|
||||
[weakSelf scanResultWithArray:@[result]];
|
||||
}];
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
case SLT_ZBar:
|
||||
{
|
||||
#ifdef LBXScan_Define_ZBar
|
||||
[LBXZBarWrapper recognizeImage:image block:^(NSArray<LBXZbarResult *> *result) {
|
||||
|
||||
//测试,只使用扫码结果第一项
|
||||
LBXZbarResult *firstObj = result[0];
|
||||
|
||||
LBXScanResult *scanResult = [[LBXScanResult alloc]init];
|
||||
scanResult.strScanned = firstObj.strScanned;
|
||||
scanResult.imgScanned = firstObj.imgScanned;
|
||||
scanResult.strBarCodeType = [LBXZBarWrapper convertFormat2String:firstObj.format];
|
||||
|
||||
[weakSelf scanResultWithArray:@[scanResult]];
|
||||
|
||||
}];
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
|
||||
{
|
||||
NSLog(@"cancel");
|
||||
|
||||
[picker dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
|
||||
#ifdef LBXScan_Define_ZXing
|
||||
- (NSString*)convertZXBarcodeFormat:(ZXBarcodeFormat)barCodeFormat
|
||||
{
|
||||
NSString *strAVMetadataObjectType = nil;
|
||||
|
||||
switch (barCodeFormat) {
|
||||
case kBarcodeFormatQRCode:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeQRCode;
|
||||
break;
|
||||
case kBarcodeFormatEan13:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeEAN13Code;
|
||||
break;
|
||||
case kBarcodeFormatEan8:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeEAN8Code;
|
||||
break;
|
||||
case kBarcodeFormatPDF417:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypePDF417Code;
|
||||
break;
|
||||
case kBarcodeFormatAztec:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeAztecCode;
|
||||
break;
|
||||
case kBarcodeFormatCode39:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeCode39Code;
|
||||
break;
|
||||
case kBarcodeFormatCode93:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeCode93Code;
|
||||
break;
|
||||
case kBarcodeFormatCode128:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeCode128Code;
|
||||
break;
|
||||
case kBarcodeFormatDataMatrix:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeDataMatrixCode;
|
||||
break;
|
||||
case kBarcodeFormatITF:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeITF14Code;
|
||||
break;
|
||||
case kBarcodeFormatRSS14:
|
||||
break;
|
||||
case kBarcodeFormatRSSExpanded:
|
||||
break;
|
||||
case kBarcodeFormatUPCA:
|
||||
break;
|
||||
case kBarcodeFormatUPCE:
|
||||
strAVMetadataObjectType = AVMetadataObjectTypeUPCECode;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return strAVMetadataObjectType;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
- (NSString*)nativeCodeWithType:(SCANCODETYPE)type
|
||||
{
|
||||
switch (type) {
|
||||
case SCT_QRCode:
|
||||
return AVMetadataObjectTypeQRCode;
|
||||
break;
|
||||
case SCT_BarCode93:
|
||||
return AVMetadataObjectTypeCode93Code;
|
||||
break;
|
||||
case SCT_BarCode128:
|
||||
return AVMetadataObjectTypeCode128Code;
|
||||
break;
|
||||
case SCT_BarCodeITF:
|
||||
return @"ITF条码:only ZXing支持";
|
||||
break;
|
||||
case SCT_BarEAN13:
|
||||
return AVMetadataObjectTypeEAN13Code;
|
||||
break;
|
||||
|
||||
default:
|
||||
return AVMetadataObjectTypeQRCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showError:(NSString*)str
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion
|
||||
{
|
||||
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
|
||||
{
|
||||
AVAuthorizationStatus permission =
|
||||
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
|
||||
switch (permission) {
|
||||
case AVAuthorizationStatusAuthorized:
|
||||
completion(YES);
|
||||
break;
|
||||
case AVAuthorizationStatusDenied:
|
||||
case AVAuthorizationStatusRestricted:
|
||||
completion(NO);
|
||||
break;
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||
completionHandler:^(BOOL granted) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (granted) {
|
||||
completion(true);
|
||||
} else {
|
||||
completion(false);
|
||||
}
|
||||
});
|
||||
|
||||
}];
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+ (BOOL)photoPermission
|
||||
{
|
||||
if (@available(iOS 8.0, *)) {
|
||||
|
||||
PHAuthorizationStatus authorStatus = [PHPhotoLibrary authorizationStatus];
|
||||
if ( authorStatus == PHAuthorizationStatusDenied ) {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
|
||||
|
||||
if ( author == ALAuthorizationStatusDenied ) {
|
||||
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@end
|
119
Classes_cocos/LBXNative/LBXScanViewStyle.h
Normal file
@ -0,0 +1,119 @@
|
||||
//
|
||||
// LBXScanViewStyle.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
// Created by lbxia on 15/11/15.
|
||||
// Copyright © 2015年 lbxia. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
/**
|
||||
扫码区域动画效果
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger,LBXScanViewAnimationStyle)
|
||||
{
|
||||
LBXScanViewAnimationStyle_LineMove, //线条上下移动
|
||||
LBXScanViewAnimationStyle_NetGrid,//网格
|
||||
LBXScanViewAnimationStyle_LineStill,//线条停止在扫码区域中央
|
||||
LBXScanViewAnimationStyle_None //无动画
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
扫码区域4个角位置类型
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, LBXScanViewPhotoframeAngleStyle)
|
||||
{
|
||||
LBXScanViewPhotoframeAngleStyle_Inner,//内嵌,一般不显示矩形框情况下
|
||||
LBXScanViewPhotoframeAngleStyle_Outer,//外嵌,包围在矩形框的4个角
|
||||
LBXScanViewPhotoframeAngleStyle_On //在矩形框的4个角上,覆盖
|
||||
};
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LBXScanViewStyle : NSObject
|
||||
|
||||
|
||||
#pragma mark -中心位置矩形框
|
||||
/**
|
||||
@brief 是否需要绘制扫码矩形框,默认YES
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isNeedShowRetangle;
|
||||
|
||||
|
||||
/**
|
||||
* 默认扫码区域为正方形,如果扫码区域不是正方形,设置宽高比
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat whRatio;
|
||||
|
||||
|
||||
/**
|
||||
@brief 矩形框(视频显示透明区)域向上移动偏移量,0表示扫码透明区域在当前视图中心位置,< 0 表示扫码区域下移, >0 表示扫码区域上移
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat centerUpOffset;
|
||||
|
||||
/**
|
||||
* 矩形框(视频显示透明区)域离界面左边及右边距离,默认60
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat xScanRetangleOffset;
|
||||
|
||||
/**
|
||||
@brief 矩形框线条颜色
|
||||
*/
|
||||
@property (nonatomic, strong) UIColor *colorRetangleLine;
|
||||
|
||||
|
||||
|
||||
#pragma mark -矩形框(扫码区域)周围4个角
|
||||
/**
|
||||
@brief 扫码区域的4个角类型
|
||||
*/
|
||||
@property (nonatomic, assign) LBXScanViewPhotoframeAngleStyle photoframeAngleStyle;
|
||||
|
||||
//4个角的颜色
|
||||
@property (nonatomic, strong) UIColor* colorAngle;
|
||||
|
||||
//扫码区域4个角的宽度和高度
|
||||
@property (nonatomic, assign) CGFloat photoframeAngleW;
|
||||
@property (nonatomic, assign) CGFloat photoframeAngleH;
|
||||
/**
|
||||
@brief 扫码区域4个角的线条宽度,默认6,建议8到4之间
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat photoframeLineW;
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark --动画效果
|
||||
/**
|
||||
@brief 扫码动画效果:线条或网格
|
||||
*/
|
||||
@property (nonatomic, assign) LBXScanViewAnimationStyle anmiationStyle;
|
||||
|
||||
/**
|
||||
* 动画效果的图像,如线条或网格的图像,如果为nil,表示不需要动画效果
|
||||
*/
|
||||
@property (nonatomic,strong,nullable) UIImage *animationImage;
|
||||
|
||||
|
||||
|
||||
#pragma mark -非识别区域颜色,默认 RGBA (0,0,0,0.5)
|
||||
|
||||
/**
|
||||
must be create by [UIColor colorWithRed: green: blue: alpha:]
|
||||
*/
|
||||
@property (nonatomic, strong) UIColor *notRecoginitonArea;
|
||||
|
||||
|
||||
/// 生成路径
|
||||
/// @param name CodeScan.bundle内的文件名称
|
||||
+ (NSString*)imagePathWithName:(NSString*)name;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
52
Classes_cocos/LBXNative/LBXScanViewStyle.m
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// LBXScanViewStyle.m
|
||||
//
|
||||
//
|
||||
// Created by lbxia on 15/11/15.
|
||||
// Copyright © 2015年 lbxia. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LBXScanViewStyle.h"
|
||||
|
||||
@implementation LBXScanViewStyle
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_isNeedShowRetangle = YES;
|
||||
|
||||
_whRatio = 1.0;
|
||||
|
||||
_colorRetangleLine = [UIColor whiteColor];
|
||||
|
||||
_centerUpOffset = 44;
|
||||
_xScanRetangleOffset = 60;
|
||||
|
||||
_anmiationStyle = LBXScanViewAnimationStyle_LineMove;
|
||||
_photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Outer;
|
||||
_colorAngle = [UIColor colorWithRed:0. green:167./255. blue:231./255. alpha:1.0];
|
||||
|
||||
_notRecoginitonArea = [UIColor colorWithRed:0. green:.0 blue:.0 alpha:.5];
|
||||
|
||||
|
||||
_photoframeAngleW = 24;
|
||||
_photoframeAngleH = 24;
|
||||
_photoframeLineW = 7;
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSString*)imagePathWithName:(NSString*)name
|
||||
{
|
||||
NSString *bundlePath = [[NSBundle bundleForClass:self.class] pathForResource:@"CodeScan" ofType:@"bundle"];
|
||||
|
||||
NSString* path = [NSString stringWithFormat:@"%@/%@",bundlePath, name];
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@end
|
||||
|
38
Classes_cocos/LBXNative/QQScanNativeViewController.h
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// SubLBXScanViewController.h
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
#import "LBXScanNativeViewController.h"
|
||||
|
||||
#pragma mark
|
||||
//继承LBXScanViewController,在界面上绘制想要的按钮,提示语等
|
||||
@interface QQScanNativeViewController : LBXScanNativeViewController
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief 扫码区域上方提示文字
|
||||
*/
|
||||
@property (nonatomic, strong) UILabel *topTitle;
|
||||
|
||||
#pragma mark --增加拉近/远视频界面
|
||||
@property (nonatomic, assign) BOOL isVideoZoom;
|
||||
|
||||
#pragma mark - 底部几个功能:开启闪光灯、相册、我的二维码
|
||||
//底部显示的功能项
|
||||
@property (nonatomic, strong) UIView *bottomItemsView;
|
||||
//相册
|
||||
@property (nonatomic, strong) UIButton *btnPhoto;
|
||||
//闪光灯
|
||||
@property (nonatomic, strong) UIButton *btnFlash;
|
||||
//我的二维码
|
||||
@property (nonatomic, strong) UIButton *btnMyQR;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
290
Classes_cocos/LBXNative/QQScanNativeViewController.m
Normal file
@ -0,0 +1,290 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#import "QQScanNativeViewController.h"
|
||||
#import "CreateBarCodeViewController.h"
|
||||
#import "ScanResultViewController.h"
|
||||
#import "LBXScanVideoZoomView.h"
|
||||
#import "LBXPermission.h"
|
||||
#import "LBXPermissionSetting.h"
|
||||
|
||||
@interface QQScanNativeViewController ()
|
||||
@property (nonatomic, strong) LBXScanVideoZoomView *zoomView;
|
||||
@property (nonatomic, assign) CGFloat maxVideoScale;
|
||||
@end
|
||||
|
||||
@implementation QQScanNativeViewController
|
||||
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
|
||||
//设置扫码后需要扫码图像
|
||||
self.isNeedScanImage = YES;
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
|
||||
if (_topTitle) {
|
||||
|
||||
_topTitle.bounds = CGRectMake(0, 0, 145, 60);
|
||||
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 50);
|
||||
}
|
||||
|
||||
if (_bottomItemsView) {
|
||||
|
||||
CGRect frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds)-100,
|
||||
CGRectGetWidth(self.view.bounds), 100);
|
||||
|
||||
self.bottomItemsView.frame = frame;
|
||||
CGSize size = CGSizeMake(65, 87);
|
||||
|
||||
_btnFlash.bounds = CGRectMake(0, 0, size.width, size.height);
|
||||
_btnFlash.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/2, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
|
||||
_btnPhoto.bounds = _btnFlash.bounds;
|
||||
_btnPhoto.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/4, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
|
||||
_btnMyQR.bounds = _btnFlash.bounds;
|
||||
_btnMyQR.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame) * 3/4, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
}
|
||||
|
||||
|
||||
if (_zoomView) {
|
||||
|
||||
CGRect frame = self.view.frame;
|
||||
|
||||
int XRetangleLeft = self.style.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(frame.size.width - XRetangleLeft*2, frame.size.width - XRetangleLeft*2);
|
||||
|
||||
if (self.style.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / self.style.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height/2.0 - self.style.centerUpOffset;
|
||||
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
|
||||
|
||||
CGFloat zoomw = sizeRetangle.width + 40;
|
||||
_zoomView.frame = CGRectMake((CGRectGetWidth(self.view.frame)-zoomw)/2, YMaxRetangle + 40, zoomw, 18);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
[self drawBottomItems];
|
||||
[self drawTitle];
|
||||
}
|
||||
|
||||
//绘制扫描区域
|
||||
- (void)drawTitle
|
||||
{
|
||||
if (!_topTitle)
|
||||
{
|
||||
self.topTitle = [[UILabel alloc]init];
|
||||
_topTitle.bounds = CGRectMake(0, 0, 145, 60);
|
||||
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 50);
|
||||
|
||||
//3.5inch iphone
|
||||
if ([UIScreen mainScreen].bounds.size.height <= 568 )
|
||||
{
|
||||
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 38);
|
||||
_topTitle.font = [UIFont systemFontOfSize:14];
|
||||
}
|
||||
|
||||
|
||||
_topTitle.textAlignment = NSTextAlignmentCenter;
|
||||
_topTitle.numberOfLines = 0;
|
||||
_topTitle.text = @"将取景框对准二维码即可自动扫描";
|
||||
_topTitle.textColor = [UIColor whiteColor];
|
||||
// [self.view addSubview:_topTitle];
|
||||
|
||||
[self.view insertSubview:_topTitle atIndex:3];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cameraInitOver
|
||||
{
|
||||
if (self.isVideoZoom) {
|
||||
[self zoomView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setVideoMaxScale:(CGFloat)maxScale
|
||||
{
|
||||
if (_isVideoZoom) {
|
||||
self.maxVideoScale = maxScale;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self zoomView];
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (LBXScanVideoZoomView*)zoomView
|
||||
{
|
||||
if (!_zoomView)
|
||||
{
|
||||
|
||||
CGRect frame = self.view.frame;
|
||||
|
||||
int XRetangleLeft = self.style.xScanRetangleOffset;
|
||||
|
||||
CGSize sizeRetangle = CGSizeMake(frame.size.width - XRetangleLeft*2, frame.size.width - XRetangleLeft*2);
|
||||
|
||||
if (self.style.whRatio != 1)
|
||||
{
|
||||
CGFloat w = sizeRetangle.width;
|
||||
CGFloat h = w / self.style.whRatio;
|
||||
|
||||
NSInteger hInt = (NSInteger)h;
|
||||
h = hInt;
|
||||
|
||||
sizeRetangle = CGSizeMake(w, h);
|
||||
}
|
||||
|
||||
//扫码区域Y轴最小坐标
|
||||
CGFloat YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height/2.0 - self.style.centerUpOffset;
|
||||
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
|
||||
|
||||
CGFloat zoomw = sizeRetangle.width + 40;
|
||||
_zoomView = [[LBXScanVideoZoomView alloc]initWithFrame:CGRectMake((CGRectGetWidth(self.view.frame)-zoomw)/2, YMaxRetangle + 40, zoomw, 18)];
|
||||
|
||||
[_zoomView setMaximunValue:self.maxVideoScale/2];
|
||||
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
_zoomView.block= ^(float value)
|
||||
{
|
||||
[weakSelf.scanObj setVideoScale:value];
|
||||
};
|
||||
|
||||
[self.view insertSubview:_zoomView atIndex:3];
|
||||
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
|
||||
[self.view addGestureRecognizer:tap];
|
||||
}
|
||||
|
||||
return _zoomView;
|
||||
|
||||
}
|
||||
|
||||
- (void)tap
|
||||
{
|
||||
_zoomView.hidden = !_zoomView.hidden;
|
||||
}
|
||||
|
||||
- (void)drawBottomItems
|
||||
{
|
||||
if (_bottomItemsView) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CGRect frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds)-100,
|
||||
CGRectGetWidth(self.view.bounds), 100);
|
||||
|
||||
|
||||
self.bottomItemsView = [[UIView alloc]initWithFrame:frame];
|
||||
|
||||
_bottomItemsView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
_bottomItemsView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
|
||||
#endif
|
||||
|
||||
[self.view insertSubview:_bottomItemsView atIndex:3];
|
||||
|
||||
|
||||
CGSize size = CGSizeMake(65, 87);
|
||||
self.btnFlash = [[UIButton alloc]init];
|
||||
_btnFlash.bounds = CGRectMake(0, 0, size.width, size.height);
|
||||
_btnFlash.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/2, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_nor"] forState:UIControlStateNormal];
|
||||
[_btnFlash addTarget:self action:@selector(openOrCloseFlash) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
self.btnPhoto = [[UIButton alloc]init];
|
||||
_btnPhoto.bounds = _btnFlash.bounds;
|
||||
_btnPhoto.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/4, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
[_btnPhoto setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_photo_nor"] forState:UIControlStateNormal];
|
||||
[_btnPhoto setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_photo_down"] forState:UIControlStateHighlighted];
|
||||
[_btnPhoto addTarget:self action:@selector(openPhoto) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
self.btnMyQR = [[UIButton alloc]init];
|
||||
_btnMyQR.bounds = _btnFlash.bounds;
|
||||
_btnMyQR.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame) * 3/4, CGRectGetHeight(_bottomItemsView.frame)/2);
|
||||
[_btnMyQR setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_myqrcode_nor"] forState:UIControlStateNormal];
|
||||
[_btnMyQR setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_myqrcode_down"] forState:UIControlStateHighlighted];
|
||||
[_btnMyQR addTarget:self action:@selector(myQRCode) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
[_bottomItemsView addSubview:_btnFlash];
|
||||
[_bottomItemsView addSubview:_btnPhoto];
|
||||
[_bottomItemsView addSubview:_btnMyQR];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -底部功能项
|
||||
//打开相册
|
||||
- (void)openPhoto
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[LBXPermission authorizeWithType:LBXPermissionType_Photos completion:^(BOOL granted, BOOL firstTime) {
|
||||
if (granted) {
|
||||
[weakSelf openLocalPhoto:NO];
|
||||
}
|
||||
else if (!firstTime )
|
||||
{
|
||||
[LBXPermissionSetting showAlertToDislayPrivacySettingWithTitle:@"提示" msg:@"没有相册权限,是否前往设置" cancel:@"取消" setting:@"设置"];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
//开关闪光灯
|
||||
- (void)openOrCloseFlash
|
||||
{
|
||||
[super openOrCloseFlash];
|
||||
|
||||
if (self.isOpenFlash)
|
||||
{
|
||||
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_down"] forState:UIControlStateNormal];
|
||||
}
|
||||
else
|
||||
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_nor"] forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -底部功能项
|
||||
|
||||
|
||||
- (void)myQRCode
|
||||
{
|
||||
CreateBarCodeViewController *vc = [CreateBarCodeViewController new];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
|
||||
@end
|
16
Classes_cocos/LBXNative/ScanResultViewController.h
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// ScanResultViewController.h
|
||||
// LBXScanDemo
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ScanResultViewController : UIViewController
|
||||
|
||||
@property (nonatomic, strong) UIImage* imgScan;
|
||||
@property (nonatomic, copy) NSString* strScan;
|
||||
|
||||
@property (nonatomic,copy)NSString *strCodeType;
|
||||
|
||||
@end
|
43
Classes_cocos/LBXNative/ScanResultViewController.m
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// ScanResultViewController.m
|
||||
// LBXScanDemo
|
||||
//
|
||||
|
||||
#import "ScanResultViewController.h"
|
||||
|
||||
@interface ScanResultViewController ()
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *scanImg;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *labelScanText;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *labelScanCodeType;
|
||||
@end
|
||||
|
||||
@implementation ScanResultViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view from its nib.
|
||||
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
|
||||
if (!_imgScan) {
|
||||
|
||||
_scanImg.backgroundColor = [UIColor grayColor];
|
||||
}
|
||||
|
||||
_scanImg.image = _imgScan;
|
||||
_labelScanText.text = _strScan;
|
||||
_labelScanCodeType.text = [NSString stringWithFormat:@"码的类型:%@",_strCodeType];
|
||||
}
|
||||
|
||||
|
||||
@end
|
61
Classes_cocos/LBXNative/ScanResultViewController.xib
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ScanResultViewController">
|
||||
<connections>
|
||||
<outlet property="labelScanCodeType" destination="cfU-Y2-7od" id="6zx-aA-Ss7"/>
|
||||
<outlet property="labelScanText" destination="O9L-0W-wec" id="dvp-ut-CAV"/>
|
||||
<outlet property="scanImg" destination="3Fg-0B-ez0" id="H7c-ka-lhi"/>
|
||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3Fg-0B-ez0">
|
||||
<rect key="frame" x="67.5" y="15" width="240" height="248"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="DQA-2S-Ytt"/>
|
||||
<constraint firstAttribute="height" constant="248" id="nRp-Sr-C81"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O9L-0W-wec">
|
||||
<rect key="frame" x="22" y="342" width="331" height="317"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="码的类型:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cfU-Y2-7od">
|
||||
<rect key="frame" x="57.5" y="283" width="260" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="260" id="B8h-6b-aaQ"/>
|
||||
<constraint firstAttribute="height" constant="21" id="TEu-B6-VPf"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="O9L-0W-wec" firstAttribute="top" secondItem="cfU-Y2-7od" secondAttribute="bottom" constant="38" id="OIf-1p-ghO"/>
|
||||
<constraint firstItem="cfU-Y2-7od" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="RB8-3l-N0Y"/>
|
||||
<constraint firstItem="O9L-0W-wec" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="22" id="VBj-gH-cKh"/>
|
||||
<constraint firstItem="3Fg-0B-ez0" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="15" id="Vys-AE-3EB"/>
|
||||
<constraint firstAttribute="trailing" secondItem="O9L-0W-wec" secondAttribute="trailing" constant="22" id="Xdw-Ec-kzJ"/>
|
||||
<constraint firstItem="cfU-Y2-7od" firstAttribute="top" secondItem="3Fg-0B-ez0" secondAttribute="bottom" constant="20" id="Xra-VX-BrP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="O9L-0W-wec" secondAttribute="bottom" constant="8" id="gBR-n8-CSE"/>
|
||||
<constraint firstItem="3Fg-0B-ez0" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="n9Y-cz-9w4"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="-237" y="10"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
48
Classes_cocos/LBXNative/StyleDIY.h
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// DemoListViewModel.h
|
||||
// LBXScanDemo
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "LBXScanViewStyle.h"
|
||||
#import "LBXScanViewController.h"
|
||||
|
||||
|
||||
@interface StyleDIY : NSObject
|
||||
|
||||
#pragma mark -模仿qq界面
|
||||
+ (LBXScanViewStyle*)qqStyle;
|
||||
|
||||
#pragma mark --模仿支付宝
|
||||
+ (LBXScanViewStyle*)ZhiFuBaoStyle;
|
||||
|
||||
#pragma mark -无边框,内嵌4个角
|
||||
+ (LBXScanViewStyle*)InnerStyle;
|
||||
|
||||
#pragma mark -无边框,内嵌4个角
|
||||
+ (LBXScanViewStyle*)weixinStyle;
|
||||
|
||||
#pragma mark -框内区域识别
|
||||
+ (LBXScanViewStyle*)recoCropRect;
|
||||
|
||||
#pragma mark -4个角在矩形框线上,网格动画
|
||||
+ (LBXScanViewStyle*)OnStyle;
|
||||
|
||||
#pragma mark -自定义4个角及矩形框颜色
|
||||
+ (LBXScanViewStyle*)changeColor;
|
||||
|
||||
#pragma mark -改变扫码区域位置
|
||||
+ (LBXScanViewStyle*)changeSize;
|
||||
|
||||
#pragma mark -非正方形,可以用在扫码条形码界面
|
||||
+ (LBXScanViewStyle*)notSquare;
|
||||
|
||||
+ (AVCaptureVideoOrientation)videoOrientation;
|
||||
|
||||
|
||||
+ (NSString*)nativeCodeWithType:(SCANCODETYPE)type;
|
||||
|
||||
|
||||
@end
|
423
Classes_cocos/LBXNative/StyleDIY.m
Normal file
@ -0,0 +1,423 @@
|
||||
//
|
||||
// DemoListViewModel.m
|
||||
// LBXScanDemo
|
||||
//
|
||||
// Created by lbxia on 2017/4/1.
|
||||
// Copyright © 2017年 lbx. All rights reserved.
|
||||
//
|
||||
|
||||
#import "StyleDIY.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation StyleDIY
|
||||
|
||||
|
||||
+ (BOOL)isLandScape
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
BOOL landScape = NO;
|
||||
|
||||
|
||||
switch (orientation) {
|
||||
case UIDeviceOrientationPortrait: {
|
||||
landScape = NO;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft: {
|
||||
landScape = YES;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight: {
|
||||
|
||||
landScape = YES;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationPortraitUpsideDown: {
|
||||
|
||||
landScape = NO;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return landScape;
|
||||
|
||||
}
|
||||
|
||||
+ (AVCaptureVideoOrientation)videoOrientation
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
|
||||
|
||||
switch (orientation) {
|
||||
case UIDeviceOrientationPortrait: {
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeRight : {
|
||||
return AVCaptureVideoOrientationLandscapeLeft;
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationLandscapeLeft: {
|
||||
return AVCaptureVideoOrientationLandscapeRight;
|
||||
|
||||
}
|
||||
break;
|
||||
case UIDeviceOrientationPortraitUpsideDown: {
|
||||
return AVCaptureVideoOrientationPortraitUpsideDown;
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
break;
|
||||
}
|
||||
|
||||
return AVCaptureVideoOrientationPortrait;
|
||||
}
|
||||
|
||||
#pragma mark -模仿qq界面
|
||||
+ (LBXScanViewStyle*)qqStyle
|
||||
{
|
||||
//设置扫码区域参数设置
|
||||
|
||||
//创建参数对象
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
|
||||
//矩形区域中心上移,默认中心点为屏幕中心点
|
||||
style.centerUpOffset = 44;
|
||||
|
||||
//扫码框周围4个角的类型,设置为外挂式
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Outer;
|
||||
|
||||
//扫码框周围4个角绘制的线条宽度
|
||||
style.photoframeLineW = 6;
|
||||
|
||||
//扫码框周围4个角的宽度
|
||||
style.photoframeAngleW = 24;
|
||||
|
||||
//扫码框周围4个角的高度
|
||||
style.photoframeAngleH = 24;
|
||||
|
||||
//扫码框内 动画类型 --线条上下移动
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
|
||||
|
||||
//线条上下移动图片
|
||||
style.animationImage = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark --模仿支付宝
|
||||
+ (LBXScanViewStyle*)ZhiFuBaoStyle
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
style.centerUpOffset = 60;
|
||||
style.xScanRetangleOffset = 30;
|
||||
|
||||
if ([UIScreen mainScreen].bounds.size.height <= 480 )
|
||||
{
|
||||
//3.5inch 显示的扫码缩小
|
||||
style.centerUpOffset = 40;
|
||||
style.xScanRetangleOffset = 40;
|
||||
}
|
||||
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
|
||||
style.photoframeLineW = 2.0;
|
||||
style.photoframeAngleW = 16;
|
||||
style.photoframeAngleH = 16;
|
||||
|
||||
style.isNeedShowRetangle = NO;
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
|
||||
//使用的支付宝里面网格图片
|
||||
UIImage *imgFullNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_full_net"];
|
||||
style.animationImage = imgFullNet;
|
||||
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
+ (void)modifyLandScape:(LBXScanViewStyle*)style
|
||||
{
|
||||
if ([self isLandScape]) {
|
||||
|
||||
style.centerUpOffset = 20;
|
||||
|
||||
CGFloat w = [UIScreen mainScreen].bounds.size.width;
|
||||
CGFloat h = [UIScreen mainScreen].bounds.size.height;
|
||||
|
||||
CGFloat max = MAX(w, h);
|
||||
|
||||
CGFloat min = MIN(w, h);
|
||||
|
||||
CGFloat scanRetangeH = min / 3;
|
||||
|
||||
style.xScanRetangleOffset = max / 2 - scanRetangeH / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
style.centerUpOffset = 40;
|
||||
style.xScanRetangleOffset = 60;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -无边框,内嵌4个角
|
||||
+ (LBXScanViewStyle*)InnerStyle
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
style.centerUpOffset = 44;
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
|
||||
style.photoframeLineW = 3;
|
||||
style.photoframeAngleW = 18;
|
||||
style.photoframeAngleH = 18;
|
||||
style.isNeedShowRetangle = NO;
|
||||
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
|
||||
|
||||
//qq里面的线条图片
|
||||
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
|
||||
style.animationImage = imgLine;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -无边框,内嵌4个角
|
||||
+ (LBXScanViewStyle*)weixinStyle
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
|
||||
style.centerUpOffset = 44;
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
|
||||
style.photoframeLineW = 2;
|
||||
style.photoframeAngleW = 18;
|
||||
style.photoframeAngleH = 18;
|
||||
style.isNeedShowRetangle = YES;
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
|
||||
style.colorAngle = [UIColor colorWithRed:0./255 green:200./255. blue:20./255. alpha:1.0];
|
||||
|
||||
//qq里面的线条图片
|
||||
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_Scan_weixin_Line"];
|
||||
style.animationImage = imgLine;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -框内区域识别
|
||||
+ (LBXScanViewStyle*)recoCropRect
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
|
||||
style.centerUpOffset = 44;
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
|
||||
style.photoframeLineW = 6;
|
||||
style.photoframeAngleW = 24;
|
||||
style.photoframeAngleH = 24;
|
||||
style.isNeedShowRetangle = YES;
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
|
||||
//矩形框离左边缘及右边缘的距离
|
||||
style.xScanRetangleOffset = 80;
|
||||
|
||||
//使用的支付宝里面网格图片
|
||||
UIImage *imgPartNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];
|
||||
style.animationImage = imgPartNet;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -4个角在矩形框线上,网格动画
|
||||
+ (LBXScanViewStyle*)OnStyle
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
style.centerUpOffset = 44;
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
|
||||
style.photoframeLineW = 6;
|
||||
style.photoframeAngleW = 24;
|
||||
style.photoframeAngleH = 24;
|
||||
style.isNeedShowRetangle = YES;
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
|
||||
|
||||
//使用的支付宝里面网格图片
|
||||
UIImage *imgPartNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];
|
||||
style.animationImage = imgPartNet;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -自定义4个角及矩形框颜色
|
||||
+ (LBXScanViewStyle*)changeColor
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
|
||||
style.centerUpOffset = 44;
|
||||
//扫码框周围4个角的类型设置为在框的上面
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
|
||||
//扫码框周围4个角绘制线宽度
|
||||
style.photoframeLineW = 6;
|
||||
//扫码框周围4个角的宽度
|
||||
style.photoframeAngleW = 24;
|
||||
//扫码框周围4个角的高度
|
||||
style.photoframeAngleH = 24;
|
||||
//显示矩形框
|
||||
style.isNeedShowRetangle = YES;
|
||||
//动画类型:网格形式,模仿支付宝
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
|
||||
|
||||
style.animationImage = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];;
|
||||
//码框周围4个角的颜色
|
||||
style.colorAngle = [UIColor colorWithRed:65./255. green:174./255. blue:57./255. alpha:1.0];
|
||||
//矩形框颜色
|
||||
style.colorRetangleLine = [UIColor colorWithRed:247/255. green:202./255. blue:15./255. alpha:1.0];
|
||||
//非矩形框区域颜色
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:247./255. green:202./255 blue:15./255 alpha:0.2];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -改变扫码区域位置
|
||||
+ (LBXScanViewStyle*)changeSize
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
|
||||
//矩形框向上移动
|
||||
style.centerUpOffset = 60;
|
||||
//矩形框离左边缘及右边缘的距离
|
||||
style.xScanRetangleOffset = 100;
|
||||
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
|
||||
style.photoframeLineW = 6;
|
||||
style.photoframeAngleW = 24;
|
||||
style.photoframeAngleH = 24;
|
||||
style.isNeedShowRetangle = YES;
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
|
||||
|
||||
//qq里面的线条图片
|
||||
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
|
||||
style.animationImage = imgLine;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
#pragma mark -非正方形,可以用在扫码条形码界面
|
||||
|
||||
+ (UIImage*) createImageWithColor: (UIColor*) color
|
||||
{
|
||||
CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
UIGraphicsBeginImageContext(rect.size);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetFillColorWithColor(context, [color CGColor]);
|
||||
CGContextFillRect(context, rect);
|
||||
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return theImage;
|
||||
}
|
||||
|
||||
+ (LBXScanViewStyle*)notSquare
|
||||
{
|
||||
//设置扫码区域参数
|
||||
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
|
||||
style.centerUpOffset = 44;
|
||||
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
|
||||
style.photoframeLineW = 4;
|
||||
style.photoframeAngleW = 28;
|
||||
style.photoframeAngleH = 16;
|
||||
style.isNeedShowRetangle = NO;
|
||||
|
||||
style.anmiationStyle = LBXScanViewAnimationStyle_LineStill;
|
||||
style.animationImage = [[self class] createImageWithColor:[UIColor redColor]];
|
||||
//非正方形
|
||||
//设置矩形宽高比
|
||||
style.whRatio = 4.3/2.18;
|
||||
//离左边和右边距离
|
||||
style.xScanRetangleOffset = 30;
|
||||
|
||||
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
|
||||
|
||||
[self modifyLandScape:style];
|
||||
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+ (NSString*)nativeCodeWithType:(SCANCODETYPE)type
|
||||
{
|
||||
switch (type) {
|
||||
case SCT_QRCode:
|
||||
return AVMetadataObjectTypeQRCode;
|
||||
break;
|
||||
case SCT_BarCode93:
|
||||
return AVMetadataObjectTypeCode93Code;
|
||||
break;
|
||||
case SCT_BarCode128:
|
||||
return AVMetadataObjectTypeCode128Code;
|
||||
break;
|
||||
case SCT_BarCodeITF:
|
||||
return @"ITF条码:only ZXing支持";
|
||||
break;
|
||||
case SCT_BarEAN13:
|
||||
return AVMetadataObjectTypeEAN13Code;
|
||||
break;
|
||||
|
||||
default:
|
||||
return AVMetadataObjectTypeQRCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
22
Classes_cocos/LBXNative/UIImageView+CornerRadius.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// UIImageView+CornerRadius.h
|
||||
// MyPractise
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImageView (CornerRadius)
|
||||
|
||||
|
||||
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
|
||||
|
||||
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
|
||||
|
||||
- (instancetype)initWithRoundingRectImageView;
|
||||
|
||||
- (void)zy_cornerRadiusRoundingRect;
|
||||
|
||||
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color;
|
||||
|
||||
@end
|
248
Classes_cocos/LBXNative/UIImageView+CornerRadius.m
Normal file
@ -0,0 +1,248 @@
|
||||
//
|
||||
// UIImageView+CornerRadius.m
|
||||
// MyPractise
|
||||
//
|
||||
|
||||
#import "UIImageView+CornerRadius.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
const char kRadius;
|
||||
const char kRoundingCorners;
|
||||
const char kIsRounding;
|
||||
const char kHadAddObserver;
|
||||
const char kProcessedImage;
|
||||
|
||||
const char kBorderWidth;
|
||||
const char kBorderColor;
|
||||
|
||||
@interface UIImageView ()
|
||||
|
||||
@property (assign, nonatomic) CGFloat radius;
|
||||
@property (assign, nonatomic) UIRectCorner roundingCorners;
|
||||
@property (assign, nonatomic) CGFloat borderWidth;
|
||||
@property (strong, nonatomic) UIColor *borderColor;
|
||||
@property (assign, nonatomic) BOOL hadAddObserver;
|
||||
@property (assign, nonatomic) BOOL isRounding;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation UIImageView (CornerRadius)
|
||||
|
||||
/**
|
||||
* @brief init the Rounding UIImageView, no off-screen-rendered
|
||||
*/
|
||||
- (instancetype)initWithRoundingRectImageView {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self zy_cornerRadiusRoundingRect];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief init the UIImageView with cornerRadius, no off-screen-rendered
|
||||
*/
|
||||
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self zy_cornerRadiusAdvance:cornerRadius rectCornerType:rectCornerType];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief attach border for UIImageView with width & color
|
||||
*/
|
||||
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color {
|
||||
self.borderWidth = width;
|
||||
self.borderColor = color;
|
||||
}
|
||||
|
||||
#pragma mark - Kernel
|
||||
/**
|
||||
* @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered
|
||||
*/
|
||||
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
|
||||
CGSize size = self.bounds.size;
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
|
||||
if (nil == UIGraphicsGetCurrentContext()) {
|
||||
return;
|
||||
}
|
||||
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
|
||||
[cornerPath addClip];
|
||||
[image drawInRect:self.bounds];
|
||||
[self drawBorder:cornerPath];
|
||||
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
self.image = processedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers
|
||||
*/
|
||||
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor {
|
||||
CGSize size = self.bounds.size;
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
|
||||
if (nil == UIGraphicsGetCurrentContext()) {
|
||||
return;
|
||||
}
|
||||
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
|
||||
UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
|
||||
[backgroundColor setFill];
|
||||
[backgroundRect fill];
|
||||
[cornerPath addClip];
|
||||
[image drawInRect:self.bounds];
|
||||
[self drawBorder:cornerPath];
|
||||
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
self.image = processedImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set cornerRadius for UIImageView, no off-screen-rendered
|
||||
*/
|
||||
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
|
||||
self.radius = cornerRadius;
|
||||
self.roundingCorners = rectCornerType;
|
||||
self.isRounding = NO;
|
||||
|
||||
if (!self.hadAddObserver) {
|
||||
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
|
||||
self.hadAddObserver = YES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief become Rounding UIImageView, no off-screen-rendered
|
||||
*/
|
||||
- (void)zy_cornerRadiusRoundingRect {
|
||||
self.isRounding = YES;
|
||||
|
||||
if (!self.hadAddObserver) {
|
||||
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
|
||||
self.hadAddObserver = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
- (void)drawBorder:(UIBezierPath *)path {
|
||||
if (0 != self.borderWidth && nil != self.borderColor) {
|
||||
[path setLineWidth:2 * self.borderWidth];
|
||||
[self.borderColor setStroke];
|
||||
[path stroke];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (self.hadAddObserver) {
|
||||
[self removeObserver:self forKeyPath:@"image"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)validateFrame {
|
||||
if (self.frame.size.width == 0) {
|
||||
[self.class swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
Method oneMethod = class_getInstanceMethod(self, oneSel);
|
||||
Method anotherMethod = class_getInstanceMethod(self, anotherSel);
|
||||
|
||||
method_exchangeImplementations(oneMethod, anotherMethod);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)zy_LayoutSubviews {
|
||||
[super layoutSubviews];
|
||||
if (self.isRounding) {
|
||||
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
|
||||
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
|
||||
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.radius rectCornerType:self.roundingCorners];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - KVO for .image
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
if ([keyPath isEqualToString:@"image"]) {
|
||||
UIImage *newImage = change[NSKeyValueChangeNewKey];
|
||||
if ([newImage isMemberOfClass:[NSNull class]]) {
|
||||
return;
|
||||
} else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
|
||||
return;
|
||||
}
|
||||
[self validateFrame];
|
||||
if (self.isRounding) {
|
||||
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
|
||||
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
|
||||
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.radius rectCornerType:self.roundingCorners];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark property
|
||||
- (CGFloat)borderWidth {
|
||||
return [objc_getAssociatedObject(self, &kBorderWidth) floatValue];
|
||||
}
|
||||
|
||||
- (void)setBorderWidth:(CGFloat)borderWidth {
|
||||
objc_setAssociatedObject(self, &kBorderWidth, @(borderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (UIColor *)borderColor {
|
||||
return objc_getAssociatedObject(self, &kBorderColor);
|
||||
}
|
||||
|
||||
- (void)setBorderColor:(UIColor *)borderColor {
|
||||
objc_setAssociatedObject(self, &kBorderColor, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (BOOL)hadAddObserver {
|
||||
return [objc_getAssociatedObject(self, &kHadAddObserver) boolValue];
|
||||
}
|
||||
|
||||
- (void)setHadAddObserver:(BOOL)hadAddObserver {
|
||||
objc_setAssociatedObject(self, &kHadAddObserver, @(hadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (BOOL)isRounding {
|
||||
return [objc_getAssociatedObject(self, &kIsRounding) boolValue];
|
||||
}
|
||||
|
||||
- (void)setIsRounding:(BOOL)isRounding {
|
||||
objc_setAssociatedObject(self, &kIsRounding, @(isRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (UIRectCorner)roundingCorners {
|
||||
return [objc_getAssociatedObject(self, &kRoundingCorners) unsignedLongValue];
|
||||
}
|
||||
|
||||
- (void)setRoundingCorners:(UIRectCorner)roundingCorners {
|
||||
objc_setAssociatedObject(self, &kRoundingCorners, @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (CGFloat)radius {
|
||||
return [objc_getAssociatedObject(self, &kRadius) floatValue];
|
||||
}
|
||||
|
||||
- (void)setRadius:(CGFloat)radius {
|
||||
objc_setAssociatedObject(self, &kRadius, @(radius), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
194
Classes_cocos/LBXScanNative.h
Normal file
@ -0,0 +1,194 @@
|
||||
//
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
@import UIKit;
|
||||
@import Foundation;
|
||||
@import AVFoundation;
|
||||
|
||||
#import "LBXScanTypes.h"
|
||||
#define LBXScan_Define_Native
|
||||
|
||||
/**
|
||||
@brief ios系统自带扫码功能
|
||||
*/
|
||||
@interface LBXScanNative : NSObject
|
||||
|
||||
|
||||
/// 是否需要条码位置信息,默认NO,位置信息在LBXScanResult中返回
|
||||
@property (nonatomic, assign) BOOL needCodePosion;
|
||||
|
||||
///连续扫码,默认NO
|
||||
@property (nonatomic, assign) BOOL continuous;
|
||||
|
||||
//default AVCaptureVideoOrientationPortrait
|
||||
@property (nonatomic, assign) AVCaptureVideoOrientation orientation;
|
||||
@property (nonatomic, assign) CGRect videoLayerframe;
|
||||
|
||||
//相机启动完成
|
||||
@property (nonatomic, copy) void (^onStarted)(void);
|
||||
|
||||
#pragma mark --初始化
|
||||
/**
|
||||
@brief 初始化采集相机
|
||||
@param preView 视频显示区域
|
||||
@param objType 识别码类型:如果为nil,默认支持很多类型。(二维码QR:AVMetadataObjectTypeQRCode,条码如:AVMetadataObjectTypeCode93Code
|
||||
@param success 识别结果
|
||||
@return LBXScanNative的实例
|
||||
*/
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief 初始化采集相机
|
||||
@param preView 视频显示区域
|
||||
@param objType 识别码类型:如果为nil,默认支持很多类型。(二维码QR:AVMetadataObjectTypeQRCode,条码如:AVMetadataObjectTypeCode93Code
|
||||
@param blockvideoMaxScale 返回摄像头放大最大范围
|
||||
@param success 识别结果
|
||||
@return LBXScanNative的实例
|
||||
*/
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success;
|
||||
|
||||
|
||||
/**
|
||||
@brief 初始化采集相机
|
||||
@param preView 视频显示区域
|
||||
@param objType 识别码类型:如果为nil,默认支持很多类型。(二维码如QR:AVMetadataObjectTypeQRCode,条码如:AVMetadataObjectTypeCode93Code
|
||||
@param cropRect 识别区域,值CGRectZero 全屏识别
|
||||
@param success 识别结果
|
||||
@return LBXScanNative的实例
|
||||
*/
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
cropRect:(CGRect)cropRect
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success;
|
||||
|
||||
|
||||
/**
|
||||
@brief 初始化采集相机
|
||||
@param preView 视频显示区域
|
||||
@param objType 识别码类型:如果为nil,默认支持很多类型。(二维码如QR:AVMetadataObjectTypeQRCode,条码如:AVMetadataObjectTypeCode93Code
|
||||
@param cropRect 识别区域,值CGRectZero 全屏识别
|
||||
@param blockvideoMaxScale 返回摄像头放大最大范围
|
||||
@param success 识别结果
|
||||
@return LBXScanNative的实例
|
||||
*/
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
cropRect:(CGRect)cropRect
|
||||
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success;
|
||||
|
||||
|
||||
|
||||
#pragma mark --设备控制
|
||||
|
||||
/*!
|
||||
* 开始扫码
|
||||
*/
|
||||
- (void)startScan;
|
||||
|
||||
/*!
|
||||
* 停止扫码
|
||||
*/
|
||||
- (void)stopScan;
|
||||
|
||||
|
||||
/*!
|
||||
* 是否有闪光灯,在启动完成后可调用
|
||||
*/
|
||||
- (BOOL)hasTorch;
|
||||
/**
|
||||
* 开启关闭闪光灯
|
||||
*
|
||||
* @param torch ...
|
||||
*/
|
||||
- (void)setTorch:(BOOL)torch;
|
||||
|
||||
/*!
|
||||
* 自动根据闪关灯状态去改变
|
||||
*/
|
||||
- (void)changeTorch;
|
||||
|
||||
/**
|
||||
* 修改扫码类型:二维码、条形码
|
||||
*
|
||||
* @param objType type
|
||||
*/
|
||||
- (void)changeScanType:(NSArray*)objType;
|
||||
|
||||
/*!
|
||||
* 设置扫码成功后是否拍照
|
||||
*
|
||||
* @param isNeedCaputureImg YES:拍照, NO:不拍照
|
||||
*/
|
||||
- (void)setNeedCaptureImage:(BOOL)isNeedCaputureImg;
|
||||
|
||||
#pragma mark --镜头
|
||||
/**
|
||||
@brief 获取摄像机最大拉远镜头
|
||||
@return 放大系数
|
||||
*/
|
||||
- (CGFloat)getVideoMaxScale;
|
||||
|
||||
/**
|
||||
@brief 拉近拉远镜头
|
||||
@param scale 系数
|
||||
*/
|
||||
- (void)setVideoScale:(CGFloat)scale;
|
||||
|
||||
#pragma mark --识别图片
|
||||
|
||||
|
||||
/**
|
||||
识别QR二维码图片,ios8.0以上支持
|
||||
|
||||
@param image 图片
|
||||
@param block 返回识别结果
|
||||
*/
|
||||
+ (void)recognizeImage:(UIImage*)image success:(void(^)(NSArray<LBXScanResult*> *array))block;
|
||||
|
||||
#pragma mark --生成条码
|
||||
|
||||
|
||||
/**
|
||||
生成QR二维码
|
||||
|
||||
@param text 字符串
|
||||
@param size 二维码大小
|
||||
@return 返回二维码图像
|
||||
*/
|
||||
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size;
|
||||
|
||||
|
||||
/**
|
||||
生成QR二维码
|
||||
|
||||
@param text 字符串
|
||||
@param size 大小
|
||||
@param qrColor 二维码前景色
|
||||
@param bkColor 二维码背景色
|
||||
@return 二维码图像
|
||||
*/
|
||||
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size QRColor:(UIColor*)qrColor bkColor:(UIColor*)bkColor;
|
||||
|
||||
|
||||
/**
|
||||
生成条形码
|
||||
|
||||
@param text 字符串
|
||||
@param size 大小
|
||||
@return 返回条码图像
|
||||
*/
|
||||
+ (UIImage*)createBarCodeWithString:(NSString*)text QRSize:(CGSize)size;
|
||||
|
||||
@end
|
||||
|
850
Classes_cocos/LBXScanNative.m
Normal file
@ -0,0 +1,850 @@
|
||||
|
||||
|
||||
|
||||
#import "LBXScanNative.h"
|
||||
|
||||
|
||||
|
||||
@interface LBXScanNative()<AVCaptureMetadataOutputObjectsDelegate>
|
||||
{
|
||||
BOOL bNeedScanResult;
|
||||
|
||||
}
|
||||
|
||||
@property (assign,nonatomic)AVCaptureDevice * device;
|
||||
@property (strong,nonatomic)AVCaptureDeviceInput * input;
|
||||
@property (strong,nonatomic)AVCaptureMetadataOutput * output;
|
||||
@property (strong,nonatomic)AVCaptureSession * session;
|
||||
@property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;
|
||||
|
||||
@property(nonatomic,strong) AVCaptureStillImageOutput *stillImageOutput;//拍照
|
||||
|
||||
@property(nonatomic,assign)BOOL isNeedCaputureImage;
|
||||
|
||||
@property (nonatomic, assign) BOOL starting;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<LBXScanResult*> *arrayResult;
|
||||
|
||||
@property (nonatomic, strong) NSArray* arrayBarCodeType;
|
||||
|
||||
/**
|
||||
@brief 视频预览显示视图
|
||||
*/
|
||||
@property (nonatomic,weak)UIView *videoPreView;
|
||||
|
||||
|
||||
/*!
|
||||
* 扫码结果返回
|
||||
*/
|
||||
@property(nonatomic,copy)void (^blockScanResult)(NSArray<LBXScanResult*> *array);
|
||||
|
||||
@property (nonatomic, copy) void (^blockvideoMaxScale)(CGFloat maxScale);
|
||||
|
||||
@end
|
||||
|
||||
@implementation LBXScanNative
|
||||
|
||||
|
||||
- (void)setNeedCaptureImage:(BOOL)isNeedCaputureImg
|
||||
{
|
||||
_isNeedCaputureImage = isNeedCaputureImg;
|
||||
}
|
||||
|
||||
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success
|
||||
{
|
||||
if (self = [super init]) {
|
||||
|
||||
|
||||
[self initParaWithPreView:preView ObjectType:objType cropRect:CGRectZero videoMaxScale:blockvideoMaxScale success:success];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success
|
||||
{
|
||||
if (self = [super init]) {
|
||||
|
||||
[self initParaWithPreView:preView ObjectType:objType cropRect:CGRectZero videoMaxScale:nil success:success];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
cropRect:(CGRect)cropRect
|
||||
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self initParaWithPreView:preView ObjectType:objType cropRect:cropRect videoMaxScale:blockvideoMaxScale success:success];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPreView:(UIView*)preView
|
||||
ObjectType:(NSArray*)objType
|
||||
cropRect:(CGRect)cropRect
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self initParaWithPreView:preView ObjectType:objType cropRect:cropRect videoMaxScale:nil success:success];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)initParaWithPreView:(UIView*)videoPreView
|
||||
ObjectType:(NSArray*)objType
|
||||
cropRect:(CGRect)cropRect
|
||||
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
|
||||
success:(void(^)(NSArray<LBXScanResult*> *array))success
|
||||
{
|
||||
|
||||
self.needCodePosion = NO;
|
||||
self.continuous = NO;
|
||||
self.starting = NO;
|
||||
self.orientation = AVCaptureVideoOrientationPortrait;
|
||||
self.blockvideoMaxScale = blockvideoMaxScale;
|
||||
|
||||
self.arrayBarCodeType = objType;
|
||||
self.blockScanResult = success;
|
||||
self.videoPreView = videoPreView;
|
||||
|
||||
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
|
||||
if (!_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Input
|
||||
_input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
|
||||
if ( !_input )
|
||||
return ;
|
||||
|
||||
|
||||
bNeedScanResult = YES;
|
||||
|
||||
// Output
|
||||
_output = [[AVCaptureMetadataOutput alloc]init];
|
||||
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
|
||||
|
||||
if ( !CGRectEqualToRect(cropRect,CGRectZero) )
|
||||
{
|
||||
_output.rectOfInterest = cropRect;
|
||||
}
|
||||
|
||||
/*
|
||||
// Setup the still image file output
|
||||
*/
|
||||
// AVCapturePhotoOutput
|
||||
|
||||
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
|
||||
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
AVVideoCodecJPEG, AVVideoCodecKey,
|
||||
nil];
|
||||
[_stillImageOutput setOutputSettings:outputSettings];
|
||||
|
||||
// Session
|
||||
_session = [[AVCaptureSession alloc]init];
|
||||
[_session setSessionPreset:AVCaptureSessionPresetHigh];
|
||||
|
||||
// [_session setSessionPreset:AVCaptureSessionPreset1280x720];
|
||||
|
||||
if ([_session canAddInput:_input])
|
||||
{
|
||||
[_session addInput:_input];
|
||||
}
|
||||
|
||||
if ([_session canAddOutput:_output])
|
||||
{
|
||||
[_session addOutput:_output];
|
||||
}
|
||||
|
||||
if ([_session canAddOutput:_stillImageOutput])
|
||||
{
|
||||
[_session addOutput:_stillImageOutput];
|
||||
}
|
||||
|
||||
// 条码类型 AVMetadataObjectTypeQRCode
|
||||
// _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
|
||||
|
||||
if (!objType) {
|
||||
objType = [self defaultMetaDataObjectTypes];
|
||||
}
|
||||
|
||||
_output.metadataObjectTypes = objType;
|
||||
|
||||
// Preview
|
||||
_preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
|
||||
_preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
|
||||
// _preview
|
||||
|
||||
//_preview.frame =CGRectMake(20,110,280,280);
|
||||
|
||||
CGRect frame = videoPreView.frame;
|
||||
frame.origin = CGPointZero;
|
||||
_preview.frame = frame;
|
||||
|
||||
|
||||
[videoPreView.layer insertSublayer:self.preview atIndex:0];
|
||||
|
||||
|
||||
if (_blockvideoMaxScale) {
|
||||
|
||||
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
|
||||
CGFloat maxScale = videoConnection.videoMaxScaleAndCropFactor;
|
||||
CGFloat scale = videoConnection.videoScaleAndCropFactor;
|
||||
NSLog(@"max:%F cur:%f",maxScale,scale);
|
||||
|
||||
_blockvideoMaxScale(maxScale);
|
||||
}
|
||||
|
||||
|
||||
//先进行判断是否支持控制对焦,不开启自动对焦功能,很难识别二维码。
|
||||
if (_device.isFocusPointOfInterestSupported &&[_device isFocusModeSupported:AVCaptureFocusModeAutoFocus])
|
||||
{
|
||||
[_input.device lockForConfiguration:nil];
|
||||
[_input.device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
|
||||
[_input.device unlockForConfiguration];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)getVideoMaxScale
|
||||
{
|
||||
[_input.device lockForConfiguration:nil];
|
||||
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
|
||||
CGFloat maxScale = videoConnection.videoMaxScaleAndCropFactor;
|
||||
[_input.device unlockForConfiguration];
|
||||
|
||||
return maxScale;
|
||||
}
|
||||
|
||||
- (void)setVideoScale:(CGFloat)scale
|
||||
{
|
||||
[_input.device lockForConfiguration:nil];
|
||||
|
||||
|
||||
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
|
||||
|
||||
|
||||
if (scale < 1 || scale > videoConnection.videoMaxScaleAndCropFactor ) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;
|
||||
// NSLog(@"max :%f",videoConnection.videoMaxScaleAndCropFactor);
|
||||
|
||||
|
||||
videoConnection.videoScaleAndCropFactor = scale;
|
||||
|
||||
[_input.device unlockForConfiguration];
|
||||
|
||||
CGAffineTransform transform = _videoPreView.transform;
|
||||
|
||||
_videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);
|
||||
|
||||
|
||||
// CGFloat y = 0;
|
||||
// y = y + zoom > 1 ? zoom : -zoom;
|
||||
// //移动
|
||||
// _videoPreView.transform = CGAffineTransformTranslate(_videoPreView.transform, 0, y);
|
||||
|
||||
}
|
||||
|
||||
- (void)setScanRect:(CGRect)scanRect
|
||||
{
|
||||
if (_output) {
|
||||
_output.rectOfInterest = [self.preview metadataOutputRectOfInterestForRect:scanRect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)changeScanType:(NSArray*)objType
|
||||
{
|
||||
_output.metadataObjectTypes = objType;
|
||||
}
|
||||
|
||||
- (void)setOrientation:(AVCaptureVideoOrientation)orientation
|
||||
{
|
||||
_orientation = orientation;
|
||||
|
||||
if ( _input )
|
||||
{
|
||||
self.preview.connection.videoOrientation = self.orientation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)setVideoLayerframe:(CGRect)videoLayerframe
|
||||
{
|
||||
self.preview.frame = videoLayerframe;
|
||||
}
|
||||
|
||||
- (void)startScan
|
||||
{
|
||||
if ( !_starting && _input && !_session.isRunning )
|
||||
{
|
||||
_starting = YES;
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
self.preview.connection.videoOrientation = self.orientation;
|
||||
|
||||
[self.session startRunning];
|
||||
self->bNeedScanResult = YES;
|
||||
self.starting = NO;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
|
||||
[self.videoPreView.layer insertSublayer:self.preview atIndex:0];
|
||||
if (self.onStarted) {
|
||||
self.onStarted();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if ( object == _input.device ) {
|
||||
|
||||
NSLog(@"flash change");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopScan
|
||||
{
|
||||
bNeedScanResult = NO;
|
||||
if ( _input && _session.isRunning )
|
||||
{
|
||||
bNeedScanResult = NO;
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
[self.session stopRunning];
|
||||
self.starting = NO;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasTorch
|
||||
{
|
||||
return [_input.device hasTorch];
|
||||
}
|
||||
|
||||
- (void)setTorch:(BOOL)torch {
|
||||
if ([self.input.device hasTorch]) {
|
||||
NSError *error = nil;
|
||||
if([self.input.device lockForConfiguration:&error])
|
||||
self.input.device.torchMode = torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff;
|
||||
[self.input.device unlockForConfiguration];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)changeTorch
|
||||
{
|
||||
if ([self.input.device hasTorch]) {
|
||||
|
||||
AVCaptureTorchMode torch = self.input.device.torchMode;
|
||||
|
||||
switch (_input.device.torchMode) {
|
||||
case AVCaptureTorchModeAuto:
|
||||
break;
|
||||
case AVCaptureTorchModeOff:
|
||||
torch = AVCaptureTorchModeOn;
|
||||
break;
|
||||
case AVCaptureTorchModeOn:
|
||||
torch = AVCaptureTorchModeOff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
[_input.device lockForConfiguration:nil];
|
||||
_input.device.torchMode = torch;
|
||||
[_input.device unlockForConfiguration];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-(UIImage *)getImageFromLayer:(CALayer *)layer size:(CGSize)size
|
||||
{
|
||||
UIGraphicsBeginImageContextWithOptions(size, YES, [[UIScreen mainScreen]scale]);
|
||||
[layer renderInContext:UIGraphicsGetCurrentContext()];
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
- (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections
|
||||
{
|
||||
for ( AVCaptureConnection *connection in connections ) {
|
||||
for ( AVCaptureInputPort *port in [connection inputPorts] ) {
|
||||
if ( [[port mediaType] isEqual:mediaType] ) {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)captureImage
|
||||
{
|
||||
AVCaptureConnection *stillImageConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
|
||||
|
||||
|
||||
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection
|
||||
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
|
||||
{
|
||||
if (!self.continuous) {
|
||||
[self stopScan];
|
||||
}
|
||||
|
||||
if (imageDataSampleBuffer)
|
||||
{
|
||||
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
|
||||
|
||||
UIImage *img = [UIImage imageWithData:imageData];
|
||||
|
||||
for (LBXScanResult* result in self.arrayResult) {
|
||||
|
||||
result.imgScanned = img;
|
||||
}
|
||||
}
|
||||
|
||||
if (self.blockScanResult)
|
||||
{
|
||||
self.blockScanResult(self.arrayResult);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark AVCaptureMetadataOutputObjectsDelegate
|
||||
- (void)captureOutput2:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
//识别扫码类型
|
||||
for(AVMetadataObject *current in metadataObjects)
|
||||
{
|
||||
if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )
|
||||
{
|
||||
NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue];
|
||||
NSLog(@"type:%@",current.type);
|
||||
NSLog(@"result:%@",scannedResult);
|
||||
//测试可以同时识别多个二维码
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
if (!bNeedScanResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
bNeedScanResult = NO;
|
||||
|
||||
if (!_arrayResult) {
|
||||
|
||||
self.arrayResult = [NSMutableArray arrayWithCapacity:1];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_arrayResult removeAllObjects];
|
||||
}
|
||||
|
||||
metadataObjects = [self transformedCodesFromCodes:metadataObjects];
|
||||
|
||||
//识别扫码类型
|
||||
for(AVMetadataObject *current in metadataObjects)
|
||||
{
|
||||
if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )
|
||||
{
|
||||
bNeedScanResult = NO;
|
||||
|
||||
NSLog(@"type:%@",current.type);
|
||||
NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue];
|
||||
|
||||
NSArray<NSDictionary *> *corners = ((AVMetadataMachineReadableCodeObject *) current).corners;
|
||||
CGRect bounds = ((AVMetadataMachineReadableCodeObject *) current).bounds;
|
||||
|
||||
NSLog(@"corners:%@ bounds:%@",corners,NSStringFromCGRect( bounds ));
|
||||
|
||||
if (scannedResult && ![scannedResult isEqualToString:@""])
|
||||
{
|
||||
LBXScanResult *result = [LBXScanResult new];
|
||||
result.strScanned = scannedResult;
|
||||
result.strBarCodeType = current.type;
|
||||
result.corners = corners;
|
||||
result.bounds = bounds;
|
||||
|
||||
[_arrayResult addObject:result];
|
||||
}
|
||||
//测试可以同时识别多个二维码
|
||||
}
|
||||
}
|
||||
|
||||
if (_arrayResult.count < 1)
|
||||
{
|
||||
bNeedScanResult = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_continuous && !_needCodePosion && _isNeedCaputureImage)
|
||||
{
|
||||
[self captureImage];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_continuous) {
|
||||
[self stopScan];
|
||||
}
|
||||
|
||||
if (_blockScanResult) {
|
||||
_blockScanResult(_arrayResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (_continuous) {
|
||||
bNeedScanResult = YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *)transformedCodesFromCodes:(NSArray *)codes {
|
||||
NSMutableArray *transformedCodes = [NSMutableArray array];
|
||||
[codes enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
AVMetadataObject *transformedCode = [self.preview transformedMetadataObjectForMetadataObject:obj];
|
||||
[transformedCodes addObject:transformedCode];
|
||||
}];
|
||||
return [transformedCodes copy];
|
||||
}
|
||||
|
||||
- (CGPoint)pointForCorner:(NSDictionary *)corner {
|
||||
CGPoint point;
|
||||
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corner, &point);
|
||||
return point;
|
||||
}
|
||||
- (void)handCorners:(NSArray<NSDictionary *> *)corners bounds:(CGRect)bounds
|
||||
{
|
||||
CGFloat totalX = 0;
|
||||
CGFloat totalY = 0;
|
||||
|
||||
for (NSDictionary *dic in corners) {
|
||||
CGPoint pt = [self pointForCorner:dic];
|
||||
NSLog(@"pt:%@",NSStringFromCGPoint(pt));
|
||||
totalX += pt.x;
|
||||
totalY += pt.y;
|
||||
}
|
||||
|
||||
CGFloat averX = totalX / corners.count;
|
||||
CGFloat averY = totalY / corners.count;
|
||||
|
||||
|
||||
|
||||
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
|
||||
|
||||
NSLog(@"averx:%f,avery:%f minsize:%f",averX,averY,minSize);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
[self signCodeWithCenterX:averX centerY:averY];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
- (void)signCodeWithCenterX:(CGFloat)centerX centerY:(CGFloat)centerY
|
||||
{
|
||||
UIView *signView = [[UIView alloc]initWithFrame:CGRectMake(centerX-10, centerY-10, 20, 20)];
|
||||
|
||||
[self.videoPreView addSubview:signView];
|
||||
signView.backgroundColor = [UIColor redColor];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// 条码可以放到到指定位置 (条码在边缘位置,放大及平移后,导致边缘是黑色
|
||||
/// @param averX averX descriptio
|
||||
/// @param averY averY description
|
||||
/// @param bounds bounds description
|
||||
- (void)videoNearCode:(CGFloat)averX averY:(CGFloat)averY bounds:(CGRect)bounds
|
||||
{
|
||||
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
|
||||
// CGFloat y = 0;
|
||||
// y = y + zoom > 1 ? zoom : -zoom;
|
||||
// //移动
|
||||
// _videoPreView.transform = CGAffineTransformTranslate(_videoPreView.transform, 0, y);
|
||||
|
||||
CGFloat width = _videoPreView.bounds.size.width;
|
||||
CGFloat height = _videoPreView.bounds.size.height;
|
||||
|
||||
CGFloat centerX = width / 2;
|
||||
CGFloat centerY = height / 2;
|
||||
|
||||
CGFloat diffX = centerX - averX;
|
||||
CGFloat diffY = centerY - averY;
|
||||
|
||||
//计算二维码尺寸,然后计算放大比例
|
||||
CGFloat scale = 100 / minSize * 1.1;
|
||||
|
||||
|
||||
NSLog(@"diffX:%f,diffY:%f,scale:%f",diffX,diffY,scale);
|
||||
|
||||
diffX = diffX / MAX(1, scale * 0.8);
|
||||
diffY = diffY / MAX(1, scale * 0.8);
|
||||
|
||||
if (scale > 1) {
|
||||
|
||||
[_input.device lockForConfiguration:nil];
|
||||
|
||||
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
|
||||
|
||||
|
||||
if (scale < 1 || scale > videoConnection.videoMaxScaleAndCropFactor ) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;
|
||||
|
||||
videoConnection.videoScaleAndCropFactor = scale;
|
||||
|
||||
[_input.device unlockForConfiguration];
|
||||
|
||||
CGAffineTransform transform = _videoPreView.transform;
|
||||
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
|
||||
self.videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);
|
||||
}];
|
||||
|
||||
[UIView animateWithDuration:0.3 animations:^{
|
||||
|
||||
self.videoPreView.transform = CGAffineTransformTranslate(self.videoPreView.transform,diffX , diffY);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief 默认支持码的类别
|
||||
@return 支持类别 数组
|
||||
*/
|
||||
- (NSArray *)defaultMetaDataObjectTypes
|
||||
{
|
||||
NSMutableArray *types = [@[AVMetadataObjectTypeQRCode,
|
||||
AVMetadataObjectTypeUPCECode,
|
||||
AVMetadataObjectTypeCode39Code,
|
||||
AVMetadataObjectTypeCode39Mod43Code,
|
||||
AVMetadataObjectTypeEAN13Code,
|
||||
AVMetadataObjectTypeEAN8Code,
|
||||
AVMetadataObjectTypeCode93Code,
|
||||
AVMetadataObjectTypeCode128Code,
|
||||
AVMetadataObjectTypePDF417Code,
|
||||
AVMetadataObjectTypeAztecCode] mutableCopy];
|
||||
|
||||
if (@available(iOS 8.0, *)) {
|
||||
|
||||
[types addObjectsFromArray:@[
|
||||
AVMetadataObjectTypeInterleaved2of5Code,
|
||||
AVMetadataObjectTypeITF14Code,
|
||||
AVMetadataObjectTypeDataMatrixCode
|
||||
]];
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
#pragma mark --识别条码图片
|
||||
+ (void)recognizeImage:(UIImage*)image success:(void(^)(NSArray<LBXScanResult*> *array))block;
|
||||
{
|
||||
if (!image) {
|
||||
block(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
if (@available(iOS 8.0, *)) {
|
||||
|
||||
CIImage * cimg = [CIImage imageWithCGImage:image.CGImage];
|
||||
|
||||
if (!cimg) {
|
||||
block(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *features = nil;
|
||||
@try {
|
||||
CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
|
||||
features = [detector featuresInImage:cimg];
|
||||
} @catch (NSException *exception) {
|
||||
block(nil);
|
||||
return;
|
||||
} @finally {
|
||||
|
||||
}
|
||||
|
||||
NSMutableArray<LBXScanResult*> *mutableArray = [[NSMutableArray alloc]initWithCapacity:1];
|
||||
for (int index = 0; index < [features count]; index ++)
|
||||
{
|
||||
CIQRCodeFeature *feature = [features objectAtIndex:index];
|
||||
NSString *scannedResult = feature.messageString;
|
||||
LBXScanResult *item = [[LBXScanResult alloc]init];
|
||||
item.strScanned = scannedResult;
|
||||
item.strBarCodeType = CIDetectorTypeQRCode;
|
||||
item.imgScanned = image;
|
||||
[mutableArray addObject:item];
|
||||
}
|
||||
if (block) {
|
||||
block(mutableArray);
|
||||
}
|
||||
}else{
|
||||
if (block) {
|
||||
LBXScanResult *result = [[LBXScanResult alloc]init];
|
||||
result.strScanned = @"只支持ios8.0之后系统";
|
||||
block(@[result]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark --生成条码
|
||||
|
||||
//下面引用自 https://github.com/yourtion/Demo_CustomQRCode
|
||||
#pragma mark - InterpolatedUIImage
|
||||
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
|
||||
CGRect extent = CGRectIntegral(image.extent);
|
||||
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
|
||||
// 创建bitmap;
|
||||
size_t width = CGRectGetWidth(extent) * scale;
|
||||
size_t height = CGRectGetHeight(extent) * scale;
|
||||
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
|
||||
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
|
||||
CGColorSpaceRelease(cs);
|
||||
CIContext *context = [CIContext contextWithOptions:nil];
|
||||
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
|
||||
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
|
||||
CGContextScaleCTM(bitmapRef, scale, scale);
|
||||
CGContextDrawImage(bitmapRef, extent, bitmapImage);
|
||||
// 保存bitmap到图片
|
||||
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
|
||||
CGContextRelease(bitmapRef);
|
||||
CGImageRelease(bitmapImage);
|
||||
UIImage *aImage = [UIImage imageWithCGImage:scaledImage];
|
||||
CGImageRelease(scaledImage);
|
||||
return aImage;
|
||||
}
|
||||
|
||||
#pragma mark - QRCodeGenerator
|
||||
+ (CIImage *)createQRForString:(NSString *)qrString {
|
||||
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
// 创建filter
|
||||
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
|
||||
// 设置内容和纠错级别
|
||||
[qrFilter setValue:stringData forKey:@"inputMessage"];
|
||||
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
|
||||
// 返回CIImage
|
||||
return qrFilter.outputImage;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - 生成二维码,背景色及二维码颜色设置
|
||||
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size
|
||||
{
|
||||
NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
|
||||
|
||||
//生成
|
||||
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
|
||||
[qrFilter setValue:stringData forKey:@"inputMessage"];
|
||||
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
|
||||
|
||||
CIImage *qrImage = qrFilter.outputImage;
|
||||
|
||||
//绘制
|
||||
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
|
||||
UIGraphicsBeginImageContext(size);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
|
||||
UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
CGImageRelease(cgImage);
|
||||
|
||||
return codeImage;
|
||||
}
|
||||
|
||||
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size QRColor:(UIColor*)qrColor bkColor:(UIColor*)bkColor
|
||||
{
|
||||
|
||||
NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
|
||||
|
||||
//生成
|
||||
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
|
||||
[qrFilter setValue:stringData forKey:@"inputMessage"];
|
||||
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
|
||||
|
||||
|
||||
//上色
|
||||
CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
|
||||
keysAndValues:
|
||||
@"inputImage",qrFilter.outputImage,
|
||||
@"inputColor0",[CIColor colorWithCGColor:qrColor.CGColor],
|
||||
@"inputColor1",[CIColor colorWithCGColor:bkColor.CGColor],
|
||||
nil];
|
||||
|
||||
CIImage *qrImage = colorFilter.outputImage;
|
||||
|
||||
//绘制
|
||||
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
|
||||
UIGraphicsBeginImageContext(size);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
|
||||
UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
CGImageRelease(cgImage);
|
||||
|
||||
return codeImage;
|
||||
}
|
||||
|
||||
+ (UIImage*)createBarCodeWithString:(NSString*)text QRSize:(CGSize)size
|
||||
{
|
||||
|
||||
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:false];
|
||||
|
||||
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];
|
||||
|
||||
[filter setValue:data forKey:@"inputMessage"];
|
||||
|
||||
CIImage *barcodeImage = [filter outputImage];
|
||||
|
||||
// 消除模糊
|
||||
|
||||
CGFloat scaleX = size.width / barcodeImage.extent.size.width; // extent 返回图片的frame
|
||||
|
||||
CGFloat scaleY = size.height / barcodeImage.extent.size.height;
|
||||
|
||||
CIImage *transformedImage = [barcodeImage imageByApplyingTransform:CGAffineTransformScale(CGAffineTransformIdentity, scaleX, scaleY)];
|
||||
|
||||
return [UIImage imageWithCIImage:transformedImage];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
35
Classes_cocos/LBXScanTypes.h
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
//
|
||||
//
|
||||
// github:https://github.com/MxABC/LBXScan
|
||||
//
|
||||
|
||||
|
||||
@import UIKit;
|
||||
@import Foundation;
|
||||
|
||||
@interface LBXScanResult : NSObject
|
||||
|
||||
- (instancetype)initWithScanString:(NSString*)str imgScan:(UIImage*)img barCodeType:(NSString*)type;
|
||||
|
||||
/**
|
||||
@brief 条码字符串
|
||||
*/
|
||||
@property (nonatomic, copy) NSString* strScanned;
|
||||
/**
|
||||
@brief 扫码图像
|
||||
*/
|
||||
@property (nonatomic, strong) UIImage* imgScanned;
|
||||
/**
|
||||
@brief 扫码码的类型,AVMetadataObjectType 如AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code等
|
||||
*/
|
||||
@property (nonatomic, copy) NSString* strBarCodeType;
|
||||
|
||||
//条码4个角
|
||||
@property (nonatomic, copy) NSArray<NSDictionary *> *corners;
|
||||
|
||||
//没有corners精确
|
||||
@property (nonatomic, assign) CGRect bounds;
|
||||
|
||||
@end
|
||||
|
22
Classes_cocos/LBXScanTypes.m
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
|
||||
#import "LBXScanTypes.h"
|
||||
|
||||
@implementation LBXScanResult
|
||||
|
||||
- (instancetype)initWithScanString:(NSString*)str imgScan:(UIImage*)img barCodeType:(NSString*)type
|
||||
{
|
||||
if (self = [super init]) {
|
||||
|
||||
self.strScanned = str;
|
||||
self.imgScanned = img;
|
||||
self.strBarCodeType = type;
|
||||
self.bounds = CGRectZero;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
20
Classes_cocos/QrCodeViewController.h
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// QrCodeViewController.h
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by zhl on 2022/11/24.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface QrCodeViewController : UIViewController
|
||||
@property (nonatomic, strong) UIImage* imgScan;
|
||||
@property (nonatomic, copy) NSString* content;
|
||||
@property (nonatomic, copy) NSString* tipTitle;
|
||||
@property (nonatomic, assign) BOOL autosave;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
82
Classes_cocos/QrCodeViewController.m
Normal file
@ -0,0 +1,82 @@
|
||||
//
|
||||
// QrCodeViewController.m
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by zhl on 2022/11/24.
|
||||
//
|
||||
|
||||
#import "QrCodeViewController.h"
|
||||
#include "LBXScanNative.h"
|
||||
|
||||
@interface QrCodeViewController ()
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *scanImg;
|
||||
@property (weak, nonatomic) IBOutlet UIView *container;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *closeBtn;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *textView;
|
||||
@end
|
||||
|
||||
@implementation QrCodeViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
[_closeBtn addTarget:self action:@selector(dismissSelf:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.container.backgroundColor = [UIColor whiteColor];
|
||||
self.container.layer.shadowOffset = CGSizeMake(0, 2);
|
||||
self.container.layer.shadowRadius = 2;
|
||||
self.container.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
self.container.layer.shadowOpacity = 0.5;
|
||||
}
|
||||
|
||||
/*
|
||||
#pragma mark - Navigation
|
||||
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
// Get the new view controller using [segue destinationViewController].
|
||||
// Pass the selected object to the new view controller.
|
||||
}
|
||||
*/
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if (!_imgScan) {
|
||||
_scanImg.backgroundColor = [UIColor grayColor];
|
||||
if (_content) {
|
||||
CGSize _size = _scanImg.frame.size;
|
||||
_imgScan = [LBXScanNative createQRWithString:_content QRSize:_size];
|
||||
}
|
||||
}
|
||||
_titleLabel.text = _tipTitle;
|
||||
_scanImg.image = _imgScan;
|
||||
if (_autosave) {
|
||||
[self saveToPhotoLibrary];
|
||||
}
|
||||
}
|
||||
// save qr image to Camera Roll album
|
||||
-(void) saveToPhotoLibrary {
|
||||
UIGraphicsBeginImageContextWithOptions(self.container.bounds.size, NO, 0);
|
||||
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
||||
[self.container.layer renderInContext:ctx];
|
||||
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
|
||||
}
|
||||
|
||||
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
|
||||
{
|
||||
if (error) {
|
||||
NSLog(@"保存失败");
|
||||
} else {
|
||||
NSLog(@"保存成功");
|
||||
}
|
||||
}
|
||||
|
||||
-(void)dismissSelf:(UIButton *)button{
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
107
Classes_cocos/QrCodeViewController.xib
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="landscape" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="QrCodeViewController">
|
||||
<connections>
|
||||
<outlet property="closeBtn" destination="ARv-35-WSy" id="822-Id-lUS"/>
|
||||
<outlet property="container" destination="fpG-y0-v4j" id="jpQ-po-eFA"/>
|
||||
<outlet property="scanImg" destination="RbQ-nc-PEN" id="RaM-Wf-FXx"/>
|
||||
<outlet property="textView" destination="O4k-Xx-lNi" id="g5n-oI-kNK"/>
|
||||
<outlet property="titleLabel" destination="FUd-A4-OOf" id="dt5-bR-8rI"/>
|
||||
<outlet property="view" destination="iN0-l3-epB" id="SAp-0A-eXx"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="896" height="414"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="O4k-Xx-lNi">
|
||||
<rect key="frame" x="568" y="103" width="240" height="248"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="AgP-iJ-PiA"/>
|
||||
<constraint firstAttribute="height" constant="248" id="X7c-Eh-aot"/>
|
||||
</constraints>
|
||||
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
|
||||
<color key="textColor" systemColor="labelColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ARv-35-WSy">
|
||||
<rect key="frame" x="84" y="40" width="80" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="80" id="0fF-Qx-qH4"/>
|
||||
<constraint firstAttribute="height" constant="31" id="50h-Rz-9MN"/>
|
||||
</constraints>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<state key="normal" title="Close"/>
|
||||
<buttonConfiguration key="configuration" style="tinted" title="Close"/>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fpG-y0-v4j">
|
||||
<rect key="frame" x="318" y="62" width="260" height="290"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FUd-A4-OOf">
|
||||
<rect key="frame" x="111.5" y="15.5" width="37.5" height="19"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<color key="shadowColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="RbQ-nc-PEN">
|
||||
<rect key="frame" x="10" y="41" width="240" height="248"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="Cbb-mq-5af"/>
|
||||
<constraint firstAttribute="height" constant="248" id="Z3x-IW-dpK"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="FUd-A4-OOf" firstAttribute="centerY" secondItem="fpG-y0-v4j" secondAttribute="centerY" constant="-120" id="0Oc-BH-TJm"/>
|
||||
<constraint firstItem="RbQ-nc-PEN" firstAttribute="centerY" secondItem="fpG-y0-v4j" secondAttribute="centerY" constant="20" id="8Gc-BQ-00x"/>
|
||||
<constraint firstItem="RbQ-nc-PEN" firstAttribute="centerX" secondItem="fpG-y0-v4j" secondAttribute="centerX" id="kVG-XR-Utx"/>
|
||||
<constraint firstAttribute="width" constant="260" id="lFZ-QX-JYR"/>
|
||||
<constraint firstItem="FUd-A4-OOf" firstAttribute="centerX" secondItem="fpG-y0-v4j" secondAttribute="centerX" id="r3w-zS-uVw"/>
|
||||
<constraint firstAttribute="height" constant="290" id="x41-u7-bAe"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="fpG-y0-v4j" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="56v-Gg-QJh"/>
|
||||
<constraint firstItem="ARv-35-WSy" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" constant="-110" id="94T-iZ-mPQ"/>
|
||||
<constraint firstItem="ARv-35-WSy" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="40" id="96a-om-YCg"/>
|
||||
<constraint firstItem="ARv-35-WSy" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="-210" id="M0S-Ry-qx7"/>
|
||||
<constraint firstItem="fpG-y0-v4j" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Pgv-CL-voZ"/>
|
||||
<constraint firstItem="O4k-Xx-lNi" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" constant="20" id="T7p-OA-zZd"/>
|
||||
<constraint firstItem="ARv-35-WSy" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="40" id="a7T-fb-xLU"/>
|
||||
<constraint firstItem="O4k-Xx-lNi" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="240" id="zwm-x2-DV7"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="94T-iZ-mPQ"/>
|
||||
<exclude reference="M0S-Ry-qx7"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<point key="canvasLocation" x="139" y="115"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<systemColor name="labelColor">
|
||||
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
@ -14,12 +14,20 @@
|
||||
#include "JcWallet.h"
|
||||
#import <GoogleSignIn/GoogleSignIn.h>
|
||||
#include "KeyChain/DataManager.h"
|
||||
#include "permission/LBXPermission.h"
|
||||
#include "permission/LBXPermissionSetting.h"
|
||||
#include "LBXScanNative.h"
|
||||
#include "LBXScanTypes.h"
|
||||
#include "QrCodeViewController.h"
|
||||
|
||||
@import GoogleSignIn;
|
||||
|
||||
static NSString * const kClientID =
|
||||
@"53206975661-0d6q9pqljn84n9l63gm0to1ulap9cbk4.apps.googleusercontent.com";
|
||||
|
||||
@interface UIViewController (Wallet)<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
|
||||
@end
|
||||
|
||||
@implementation UIViewController (Wallet)
|
||||
|
||||
+(void)toWallet:(NSString *)url{
|
||||
@ -29,80 +37,95 @@ static NSString * const kClientID =
|
||||
|
||||
-(void)showQRCode:(NSString *) content title:(NSString *) title oid:(NSString *) oid {
|
||||
NSLog(@"showQRCode content: %@, title: %@, oid: %@", content, title, oid);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
QrCodeViewController *vc = [QrCodeViewController new];
|
||||
vc.content = content;
|
||||
vc.tipTitle = title;
|
||||
vc.autosave = TRUE;
|
||||
[self presentViewController:vc animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
-(void)loadRestoreKey:(NSString *)funid oid:(NSString *) oid{
|
||||
NSLog(@"loadRestoreKey::funid: %@, oid:%@", funid, oid);
|
||||
}
|
||||
|
||||
// save key to key chain
|
||||
-(void)saveKey:(NSString *) account key:(NSString *) key {
|
||||
// NSLog(@"saveKey::account:%@, key: %@", account, key);
|
||||
[[DataManager sharedInstanceWith: SynLock] saveKey: account key: key];
|
||||
}
|
||||
|
||||
// load key from key chain
|
||||
-(NSString *)loadKey:(NSString *) account {
|
||||
NSLog(@"loadKey::account:%@", account);
|
||||
return [[DataManager sharedInstanceWith: SynLock] loadKey: account];
|
||||
}
|
||||
|
||||
-(void)scanQRCode:(NSString *)funid title:(NSString *) title{
|
||||
NSLog(@"scanQRCode:: funId: %@ title: %@", funid, title);
|
||||
std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
if ([QRCodeReader supportsMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]) {
|
||||
static QRCodeReaderViewController *vc = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// if we are active again, we don't need to do this anymore
|
||||
if (vc == nil) {
|
||||
QRCodeReader *reader = [QRCodeReader readerWithMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
|
||||
vc = [QRCodeReaderViewController readerWithCancelButtonTitle:@"Cancel" codeReader:reader startScanningAtLoad:YES showSwitchCameraButton:YES showTorchButton:YES];
|
||||
vc.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||
}
|
||||
|
||||
[vc setCompletionWithBlock:^(NSString *resultAsString) {
|
||||
NSLog(@"Completion with result: %@", resultAsString);
|
||||
[self dismissViewControllerAnimated:YES completion:^{
|
||||
|
||||
NSString *result;
|
||||
if (resultAsString.length > 0) {
|
||||
result = [NSString stringWithFormat:@"{errcode: 0, data: '%@'}", resultAsString];
|
||||
} else {
|
||||
result = [NSString stringWithFormat:@"{errcode: 1, errmsg: 'cancel'}"];
|
||||
}
|
||||
std::string sresult = std::string([result UTF8String], [result lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
|
||||
}];
|
||||
}];
|
||||
[self presentViewController:vc animated:YES completion:NULL];
|
||||
});
|
||||
}
|
||||
else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error"
|
||||
message:@"The camera is need to scan QR codes"
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
//We add buttons to the alert controller by creating UIAlertActions:
|
||||
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:@"Cancel"
|
||||
style:UIAlertActionStyleCancel
|
||||
handler: ^(UIAlertAction *action){
|
||||
NSLog(@"alert cancel pressed");
|
||||
}]; //You can use a block here to handle a press on this button
|
||||
//
|
||||
UIAlertAction *setting = [UIAlertAction actionWithTitle:@"Setting"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler: ^(UIAlertAction *action){
|
||||
NSLog(@"setting pressed");
|
||||
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
|
||||
if ([[UIApplication sharedApplication] canOpenURL:url]){
|
||||
[[UIApplication sharedApplication] openURL:url];
|
||||
}
|
||||
}];
|
||||
[alertController addAction:actionOk];
|
||||
[alertController addAction:setting];
|
||||
[self presentViewController:alertController animated:YES completion:nil];
|
||||
});
|
||||
|
||||
std::string sresult = "{errcode: 1, errmsg: 'no camera permission'}";
|
||||
WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
|
||||
}
|
||||
NSLog(@"scanQRCode:: funId: %@ title: %@", funid, title);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self openLocalPhotoAlbum];
|
||||
});
|
||||
|
||||
// std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
// if ([QRCodeReader supportsMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]) {
|
||||
// static QRCodeReaderViewController *vc = nil;
|
||||
// static dispatch_once_t onceToken;
|
||||
//
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// // if we are active again, we don't need to do this anymore
|
||||
// if (vc == nil) {
|
||||
// QRCodeReader *reader = [QRCodeReader readerWithMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
|
||||
// vc = [QRCodeReaderViewController readerWithCancelButtonTitle:@"Cancel" codeReader:reader startScanningAtLoad:YES showSwitchCameraButton:YES showTorchButton:YES];
|
||||
// vc.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||
// }
|
||||
//
|
||||
// [vc setCompletionWithBlock:^(NSString *resultAsString) {
|
||||
// NSLog(@"Completion with result: %@", resultAsString);
|
||||
// [self dismissViewControllerAnimated:YES completion:^{
|
||||
//
|
||||
// NSString *result;
|
||||
// if (resultAsString.length > 0) {
|
||||
// result = [NSString stringWithFormat:@"{errcode: 0, data: '%@'}", resultAsString];
|
||||
// } else {
|
||||
// result = [NSString stringWithFormat:@"{errcode: 1, errmsg: 'cancel'}"];
|
||||
// }
|
||||
// std::string sresult = std::string([result UTF8String], [result lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||
// WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
|
||||
// }];
|
||||
// }];
|
||||
// [self presentViewController:vc animated:YES completion:NULL];
|
||||
// });
|
||||
// }
|
||||
// else {
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error"
|
||||
// message:@"The camera is need to scan QR codes"
|
||||
// preferredStyle:UIAlertControllerStyleAlert];
|
||||
// //We add buttons to the alert controller by creating UIAlertActions:
|
||||
// UIAlertAction *actionOk = [UIAlertAction actionWithTitle:@"Cancel"
|
||||
// style:UIAlertActionStyleCancel
|
||||
// handler: ^(UIAlertAction *action){
|
||||
// NSLog(@"alert cancel pressed");
|
||||
// }]; //You can use a block here to handle a press on this button
|
||||
// //
|
||||
// UIAlertAction *setting = [UIAlertAction actionWithTitle:@"Setting"
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler: ^(UIAlertAction *action){
|
||||
// NSLog(@"setting pressed");
|
||||
// NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
|
||||
// if ([[UIApplication sharedApplication] canOpenURL:url]){
|
||||
// [[UIApplication sharedApplication] openURL:url];
|
||||
// }
|
||||
// }];
|
||||
// [alertController addAction:actionOk];
|
||||
// [alertController addAction:setting];
|
||||
// [self presentViewController:alertController animated:YES completion:nil];
|
||||
// });
|
||||
//
|
||||
// std::string sresult = "{errcode: 1, errmsg: 'no camera permission'}";
|
||||
// WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
|
||||
// }
|
||||
}
|
||||
|
||||
-(void)signToGoogle:(NSString *) funid {
|
||||
@ -197,5 +220,81 @@ static NSString * const kClientID =
|
||||
// }];
|
||||
}
|
||||
|
||||
#pragma mark- - PhotoAlbum
|
||||
- (void)openLocalPhotoAlbum
|
||||
{
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[LBXPermission authorizeWithType:LBXPermissionType_Photos completion:^(BOOL granted, BOOL firstTime) {
|
||||
if (granted) {
|
||||
[weakSelf openLocalPhoto];
|
||||
}
|
||||
else if (!firstTime )
|
||||
{
|
||||
[LBXPermissionSetting showAlertToDislayPrivacySettingWithTitle:@"提示" msg:@"没有相册权限,是否前往设置" cancel:@"取消" setting:@"设置"];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* open local Photo Library
|
||||
*/
|
||||
- (void)openLocalPhoto
|
||||
{
|
||||
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
||||
|
||||
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
|
||||
picker.delegate = self;
|
||||
|
||||
// crash on some mobile
|
||||
picker.allowsEditing = NO;
|
||||
|
||||
[self presentViewController:picker animated:YES completion:nil];
|
||||
}
|
||||
#pragma mark- - UIImagePickerControllerDelegate
|
||||
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
|
||||
{
|
||||
[picker dismissViewControllerAnimated:YES completion:^{
|
||||
|
||||
[self handPhotoDidFinishPickingMediaWithInfo:info];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)handPhotoDidFinishPickingMediaWithInfo:(NSDictionary *)info
|
||||
{
|
||||
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
|
||||
|
||||
if (!image){
|
||||
image = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||
}
|
||||
if (@available(iOS 8.0, *)) {
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
|
||||
[weakSelf scanResultWithArray:array];
|
||||
}];
|
||||
}else{
|
||||
NSLog(@"native低于ios8.0不支持识别图片");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
|
||||
{
|
||||
if (!array || array.count < 1)
|
||||
{
|
||||
NSLog(@"error scan photo");
|
||||
return;
|
||||
}
|
||||
|
||||
for (LBXScanResult *result in array) {
|
||||
NSLog(@"scanResult:%@",result.strScanned);
|
||||
}
|
||||
|
||||
if (!array[0].strScanned || [array[0].strScanned isEqualToString:@""] ) {
|
||||
NSLog(@"识别失败了");
|
||||
return;
|
||||
}
|
||||
LBXScanResult *scanResult = array[0];
|
||||
|
||||
}
|
||||
@end
|
||||
|
71
Classes_cocos/permission/LBXPermission.h
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// LBXPermission.h
|
||||
// LBXKits
|
||||
// https://github.com/MxABC/LBXPermission
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LBXPermissionSetting.h"
|
||||
|
||||
|
||||
typedef NS_ENUM(NSInteger,LBXPermissionType)
|
||||
{
|
||||
LBXPermissionType_Location,
|
||||
LBXPermissionType_Camera,
|
||||
LBXPermissionType_Photos,
|
||||
LBXPermissionType_Contacts,
|
||||
LBXPermissionType_Reminders,
|
||||
LBXPermissionType_Calendar,
|
||||
LBXPermissionType_Microphone,
|
||||
LBXPermissionType_Health,
|
||||
LBXPermissionType_DataNetwork,
|
||||
LBXPermissionType_MediaLibrary
|
||||
};
|
||||
|
||||
@interface LBXPermission : NSObject
|
||||
|
||||
/**
|
||||
only effective for location servince,other type reture YES
|
||||
|
||||
|
||||
@param type permission type,when type is not location,return YES
|
||||
@return YES if system location privacy service enabled NO othersize
|
||||
*/
|
||||
+ (BOOL)isServicesEnabledWithType:(LBXPermissionType)type;
|
||||
|
||||
|
||||
/**
|
||||
whether device support the type
|
||||
|
||||
@param type permission type
|
||||
@return YES if device support
|
||||
|
||||
*/
|
||||
+ (BOOL)isDeviceSupportedWithType:(LBXPermissionType)type;
|
||||
|
||||
/**
|
||||
whether permission has been obtained, only return status, not request permission
|
||||
for example, u can use this method in app setting, show permission status
|
||||
in most cases, suggest call "authorizeWithType:completion" method
|
||||
|
||||
@param type permission type
|
||||
@return YES if Permission has been obtained,NO othersize
|
||||
*/
|
||||
+ (BOOL)authorizedWithType:(LBXPermissionType)type;
|
||||
|
||||
|
||||
/**
|
||||
request permission and return status in main thread by block.
|
||||
execute block immediately when permission has been requested,else request permission and waiting for user to choose "Don't allow" or "Allow"
|
||||
|
||||
@param type permission type
|
||||
@param completion May be called immediately if permission has been requested
|
||||
granted: YES if permission has been obtained, firstTime: YES if first time to request permission
|
||||
*/
|
||||
+ (void)authorizeWithType:(LBXPermissionType)type completion:(void(^)(BOOL granted,BOOL firstTime))completion;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
133
Classes_cocos/permission/LBXPermission.m
Normal file
@ -0,0 +1,133 @@
|
||||
//
|
||||
// LBXPermission.m
|
||||
// LBXKits
|
||||
|
||||
#import "LBXPermission.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <objc/message.h>
|
||||
|
||||
|
||||
typedef void(^completionPermissionHandler)(BOOL granted,BOOL firstTime);
|
||||
|
||||
|
||||
@implementation LBXPermission
|
||||
|
||||
|
||||
+ (BOOL)isServicesEnabledWithType:(LBXPermissionType)type
|
||||
{
|
||||
if (type == LBXPermissionType_Location)
|
||||
{
|
||||
SEL sel = NSSelectorFromString(@"isServicesEnabled");
|
||||
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(@"LBXPermissionLocation"), sel);
|
||||
return ret;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)isDeviceSupportedWithType:(LBXPermissionType)type
|
||||
{
|
||||
if (type == LBXPermissionType_Health) {
|
||||
|
||||
SEL sel = NSSelectorFromString(@"isHealthDataAvailable");
|
||||
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(@"LBXPermissionHealth"), sel);
|
||||
return ret;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)authorizedWithType:(LBXPermissionType)type
|
||||
{
|
||||
SEL sel = NSSelectorFromString(@"authorized");
|
||||
|
||||
NSString *strClass = nil;
|
||||
switch (type) {
|
||||
case LBXPermissionType_Location:
|
||||
strClass = @"LBXPermissionLocation";
|
||||
break;
|
||||
case LBXPermissionType_Camera:
|
||||
strClass = @"LBXPermissionCamera";
|
||||
break;
|
||||
case LBXPermissionType_Photos:
|
||||
strClass = @"LBXPermissionPhotos";
|
||||
break;
|
||||
case LBXPermissionType_Contacts:
|
||||
strClass = @"LBXPermissionContacts";
|
||||
break;
|
||||
case LBXPermissionType_Reminders:
|
||||
strClass = @"LBXPermissionReminders";
|
||||
break;
|
||||
case LBXPermissionType_Calendar:
|
||||
strClass = @"LBXPermissionCalendar";
|
||||
break;
|
||||
case LBXPermissionType_Microphone:
|
||||
strClass = @"LBXPermissionMicrophone";
|
||||
break;
|
||||
case LBXPermissionType_Health:
|
||||
strClass = @"LBXPermissionHealth";
|
||||
break;
|
||||
case LBXPermissionType_DataNetwork:
|
||||
break;
|
||||
case LBXPermissionType_MediaLibrary:
|
||||
strClass = @"LBXPermissionMediaLibrary";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (strClass) {
|
||||
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(strClass), sel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)authorizeWithType:(LBXPermissionType)type completion:(void(^)(BOOL granted,BOOL firstTime))completion
|
||||
{
|
||||
NSString *strClass = nil;
|
||||
switch (type) {
|
||||
case LBXPermissionType_Location:
|
||||
strClass = @"LBXPermissionLocation";
|
||||
break;
|
||||
case LBXPermissionType_Camera:
|
||||
strClass = @"LBXPermissionCamera";
|
||||
break;
|
||||
case LBXPermissionType_Photos:
|
||||
strClass = @"LBXPermissionPhotos";
|
||||
break;
|
||||
case LBXPermissionType_Contacts:
|
||||
strClass = @"LBXPermissionContacts";
|
||||
break;
|
||||
case LBXPermissionType_Reminders:
|
||||
strClass = @"LBXPermissionReminders";
|
||||
break;
|
||||
case LBXPermissionType_Calendar:
|
||||
strClass = @"LBXPermissionCalendar";
|
||||
break;
|
||||
case LBXPermissionType_Microphone:
|
||||
strClass = @"LBXPermissionMicrophone";
|
||||
break;
|
||||
case LBXPermissionType_Health:
|
||||
strClass = @"LBXPermissionHealth";
|
||||
break;
|
||||
case LBXPermissionType_DataNetwork:
|
||||
strClass = @"LBXPermissionData";
|
||||
break;
|
||||
case LBXPermissionType_MediaLibrary:
|
||||
strClass = @"LBXPermissionMediaLibrary";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (strClass)
|
||||
{
|
||||
SEL sel = NSSelectorFromString(@"authorizeWithCompletion:");
|
||||
((void(*)(id,SEL, completionPermissionHandler))objc_msgSend)(NSClassFromString(strClass),sel, completion);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
18
Classes_cocos/permission/LBXPermissionCamera.h
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// LBXPermissionCamera.h
|
||||
// LBXKits
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
|
||||
@interface LBXPermissionCamera : NSObject
|
||||
|
||||
+ (BOOL)authorized;
|
||||
|
||||
+ (AVAuthorizationStatus)authorizationStatus;
|
||||
|
||||
+ (void)authorizeWithCompletion:(void(^)(BOOL granted ,BOOL firstTime ))completion;
|
||||
|
||||
@end
|
71
Classes_cocos/permission/LBXPermissionCamera.m
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// LBXPermissionCamera.m
|
||||
// LBXKits
|
||||
//
|
||||
|
||||
#import "LBXPermissionCamera.h"
|
||||
|
||||
@implementation LBXPermissionCamera
|
||||
|
||||
+ (BOOL)authorized
|
||||
{
|
||||
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
|
||||
{
|
||||
AVAuthorizationStatus permission =
|
||||
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
|
||||
return permission == AVAuthorizationStatusAuthorized;
|
||||
|
||||
} else {
|
||||
// Prior to iOS 7 all apps were authorized.
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
+ (AVAuthorizationStatus)authorizationStatus
|
||||
{
|
||||
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
|
||||
{
|
||||
return [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
} else {
|
||||
// Prior to iOS 7 all apps were authorized.
|
||||
return AVAuthorizationStatusAuthorized;
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
|
||||
{
|
||||
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) {
|
||||
AVAuthorizationStatus permission =
|
||||
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
|
||||
switch (permission) {
|
||||
case AVAuthorizationStatusAuthorized:
|
||||
completion(YES,NO);
|
||||
break;
|
||||
case AVAuthorizationStatusDenied:
|
||||
case AVAuthorizationStatusRestricted:
|
||||
completion(NO,NO);
|
||||
break;
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||
completionHandler:^(BOOL granted) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(granted,YES);
|
||||
});
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Prior to iOS 7 all apps were authorized.
|
||||
completion(YES,NO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
26
Classes_cocos/permission/LBXPermissionPhotos.h
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// LBXPermissionPhotos.h
|
||||
// LBXKits
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface LBXPermissionPhotos : NSObject
|
||||
|
||||
+ (BOOL)authorized;
|
||||
|
||||
/**
|
||||
photo permission status
|
||||
|
||||
@return
|
||||
0 :NotDetermined
|
||||
1 :Restricted
|
||||
2 :Denied
|
||||
3 :Authorized
|
||||
*/
|
||||
+ (NSInteger)authorizationStatus;
|
||||
|
||||
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion;
|
||||
|
||||
@end
|
131
Classes_cocos/permission/LBXPermissionPhotos.m
Normal file
@ -0,0 +1,131 @@
|
||||
//
|
||||
// LBXPermissionPhotos.m
|
||||
// LBXKits
|
||||
//
|
||||
|
||||
#import "LBXPermissionPhotos.h"
|
||||
#import <Photos/Photos.h>
|
||||
#import <AssetsLibrary/AssetsLibrary.h>
|
||||
|
||||
|
||||
@implementation LBXPermissionPhotos
|
||||
|
||||
+ (BOOL)authorized
|
||||
{
|
||||
return [self authorizationStatus] == 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
photo permission status
|
||||
|
||||
@return
|
||||
0 :NotDetermined
|
||||
1 :Restricted
|
||||
2 :Denied
|
||||
3 :Authorized
|
||||
*/
|
||||
+ (NSInteger)authorizationStatus
|
||||
{
|
||||
if (@available(iOS 8,*))
|
||||
{
|
||||
return [PHPhotoLibrary authorizationStatus];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [ALAssetsLibrary authorizationStatus];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
|
||||
{
|
||||
if (@available(iOS 8.0, *)) {
|
||||
|
||||
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
|
||||
|
||||
switch (status) {
|
||||
case PHAuthorizationStatusAuthorized:
|
||||
{
|
||||
if (completion) {
|
||||
completion(YES,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PHAuthorizationStatusRestricted:
|
||||
case PHAuthorizationStatusDenied:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PHAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(status == PHAuthorizationStatusAuthorized,YES);
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO,NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
|
||||
switch (status) {
|
||||
case ALAuthorizationStatusAuthorized:
|
||||
{
|
||||
if (completion) {
|
||||
completion(YES, NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ALAuthorizationStatusNotDetermined:
|
||||
{
|
||||
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
|
||||
|
||||
[library enumerateGroupsWithTypes:ALAssetsGroupAll
|
||||
usingBlock:^(ALAssetsGroup *assetGroup, BOOL *stop) {
|
||||
if (*stop) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(YES, NO);
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}
|
||||
failureBlock:^(NSError *error) {
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion(NO, YES);
|
||||
});
|
||||
}
|
||||
}];
|
||||
} break;
|
||||
case ALAuthorizationStatusRestricted:
|
||||
case ALAuthorizationStatusDenied:
|
||||
{
|
||||
if (completion) {
|
||||
completion(NO, NO);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
51
Classes_cocos/permission/LBXPermissionSetting.h
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// LBXPermissionSetting.h
|
||||
// Demo
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
API_AVAILABLE(ios(8.0))
|
||||
@interface LBXPermissionSetting : NSObject
|
||||
|
||||
#pragma mark- guide user to show App privacy setting
|
||||
/**
|
||||
show App privacy settings
|
||||
*/
|
||||
+ (void)displayAppPrivacySettings;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
show dialog to guide user to show App privacy setting
|
||||
|
||||
@param title title
|
||||
@param message privacy message
|
||||
@param cancel cancel button text
|
||||
@param setting setting button text,if user tap this button ,will show App privacy setting
|
||||
*/
|
||||
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
|
||||
msg:(NSString*)message
|
||||
cancel:(NSString*)cancel
|
||||
setting:(NSString*)setting;
|
||||
|
||||
|
||||
/**
|
||||
show dialog to guide user to show App privacy setting
|
||||
|
||||
@param title title
|
||||
@param message privacy message
|
||||
@param cancel cancel button text
|
||||
@param setting setting button text,if user tap this button ,will show App privacy setting
|
||||
@param completion user has been choosed
|
||||
*/
|
||||
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
|
||||
msg:(NSString*)message
|
||||
cancel:(NSString*)cancel
|
||||
setting:(NSString*)setting
|
||||
completion:(void(^)(void))completion;
|
||||
|
||||
@end
|
111
Classes_cocos/permission/LBXPermissionSetting.m
Normal file
@ -0,0 +1,111 @@
|
||||
//
|
||||
// LBXPermissionSetting.m
|
||||
// Demo
|
||||
//
|
||||
|
||||
#import "LBXPermissionSetting.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@implementation LBXPermissionSetting
|
||||
|
||||
#pragma mark- disPlayAppPrivacySetting
|
||||
|
||||
+ (void)displayAppPrivacySettings
|
||||
{
|
||||
if (@available(iOS 8,*))
|
||||
{
|
||||
if (UIApplicationOpenSettingsURLString != NULL)
|
||||
{
|
||||
NSURL *appSettings = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
|
||||
|
||||
if (@available(iOS 10,*)) {
|
||||
[[UIApplication sharedApplication]openURL:appSettings options:@{} completionHandler:^(BOOL success) {
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[UIApplication sharedApplication]openURL:appSettings];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
show dialog to guide user to show App privacy setting
|
||||
|
||||
@param title title
|
||||
@param message privacy message
|
||||
@param cancel cancel button text
|
||||
@param setting setting button text,if user tap this button ,will show App privacy setting
|
||||
*/
|
||||
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
|
||||
msg:(NSString*)message
|
||||
cancel:(NSString*)cancel
|
||||
setting:(NSString*)setting
|
||||
{
|
||||
[self showAlertToDislayPrivacySettingWithTitle:title msg:message cancel:cancel setting:setting completion:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
show dialog to guide user to show App privacy setting
|
||||
|
||||
@param title title
|
||||
@param message privacy message
|
||||
@param cancel cancel button text
|
||||
@param setting setting button text,if user tap this button ,will show App privacy setting
|
||||
@param completion user has been choosed
|
||||
*/
|
||||
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
|
||||
msg:(NSString*)message
|
||||
cancel:(NSString*)cancel
|
||||
setting:(NSString*)setting
|
||||
completion:(void(^)(void))completion
|
||||
{
|
||||
if (@available(iOS 8,*)) {
|
||||
|
||||
UIAlertController* alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
//cancel
|
||||
UIAlertAction *action = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
|
||||
if (completion) {
|
||||
completion();
|
||||
}
|
||||
}];
|
||||
[alertController addAction:action];
|
||||
|
||||
//ok
|
||||
UIAlertAction *okAction = [UIAlertAction actionWithTitle:setting style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
|
||||
if (completion) {
|
||||
completion();
|
||||
}
|
||||
|
||||
[self displayAppPrivacySettings];
|
||||
}];
|
||||
[alertController addAction:okAction];
|
||||
|
||||
[[self currentTopViewController] presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (UIViewController*)currentTopViewController
|
||||
{
|
||||
UIViewController *currentViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
|
||||
while ([currentViewController presentedViewController]) currentViewController = [currentViewController presentedViewController];
|
||||
|
||||
if ([currentViewController isKindOfClass:[UITabBarController class]]
|
||||
&& ((UITabBarController*)currentViewController).selectedViewController != nil )
|
||||
{
|
||||
currentViewController = ((UITabBarController*)currentViewController).selectedViewController;
|
||||
}
|
||||
|
||||
while ([currentViewController isKindOfClass:[UINavigationController class]]
|
||||
&& [(UINavigationController*)currentViewController topViewController])
|
||||
{
|
||||
currentViewController = [(UINavigationController*)currentViewController topViewController];
|
||||
}
|
||||
|
||||
return currentViewController;
|
||||
}
|
||||
|
||||
@end
|
@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Restore Wallet recovery key need Photo Libray</string>
|
||||
<key>CADisableMinimumFrameDuration</key>
|
||||
<false/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
|
@ -79,10 +79,18 @@
|
||||
D0DD4D8D8AC82F06A4331428 /* libil2cpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 924940699744FB37428516DD /* libil2cpp.a */; };
|
||||
D52A8DA1288E6547006574E8 /* libuv_a.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D52A8D9F288E6547006574E8 /* libuv_a.a */; };
|
||||
D5538BA5287E9908000BDFB6 /* WalletEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */; };
|
||||
D579209F292F3C94004DBD4F /* LBXScanNative.m in Sources */ = {isa = PBXBuildFile; fileRef = D579209E292F3C94004DBD4F /* LBXScanNative.m */; };
|
||||
D57920A2292F3D28004DBD4F /* LBXScanTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = D57920A1292F3D28004DBD4F /* LBXScanTypes.m */; };
|
||||
D57920A5292F4738004DBD4F /* QrCodeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D57920A4292F4738004DBD4F /* QrCodeViewController.xib */; };
|
||||
D57920A8292F4763004DBD4F /* QrCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D57920A7292F4763004DBD4F /* QrCodeViewController.m */; };
|
||||
D589C9BB28B62D93002CAA34 /* cacert.pem in Resources */ = {isa = PBXBuildFile; fileRef = D589C9B928B62D93002CAA34 /* cacert.pem */; };
|
||||
D59AB424292DBACE00714392 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D59AB423292DBACE00714392 /* CloudKit.framework */; };
|
||||
D59AB42F292E250500714392 /* UICKeyChainStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB42E292E250500714392 /* UICKeyChainStore.m */; };
|
||||
D59AB433292E26CE00714392 /* DataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB432292E26CE00714392 /* DataManager.m */; };
|
||||
D59AB4AC292F325E00714392 /* LBXPermissionSetting.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */; };
|
||||
D59AB4AD292F325E00714392 /* LBXPermissionPhotos.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */; };
|
||||
D59AB4AE292F325E00714392 /* LBXPermissionCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */; };
|
||||
D59AB4AF292F325E00714392 /* LBXPermission.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A9292F325E00714392 /* LBXPermission.m */; };
|
||||
D5AB1D3328BF782300AA6AFA /* QRToggleTorchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2928BF782200AA6AFA /* QRToggleTorchButton.m */; };
|
||||
D5AB1D3428BF782300AA6AFA /* QRCameraSwitchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2B28BF782200AA6AFA /* QRCameraSwitchButton.m */; };
|
||||
D5AB1D3528BF782300AA6AFA /* QRCodeReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2D28BF782200AA6AFA /* QRCodeReaderViewController.m */; };
|
||||
@ -364,6 +372,13 @@
|
||||
D52A8D9F288E6547006574E8 /* libuv_a.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libuv_a.a; sourceTree = "<group>"; };
|
||||
D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WalletEvent.cpp; sourceTree = "<group>"; };
|
||||
D5538BA4287E9908000BDFB6 /* WalletEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WalletEvent.h; sourceTree = "<group>"; };
|
||||
D579209C292F3C94004DBD4F /* LBXScanNative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXScanNative.h; sourceTree = "<group>"; };
|
||||
D579209E292F3C94004DBD4F /* LBXScanNative.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXScanNative.m; sourceTree = "<group>"; };
|
||||
D57920A0292F3D28004DBD4F /* LBXScanTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXScanTypes.h; sourceTree = "<group>"; };
|
||||
D57920A1292F3D28004DBD4F /* LBXScanTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXScanTypes.m; sourceTree = "<group>"; };
|
||||
D57920A4292F4738004DBD4F /* QrCodeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QrCodeViewController.xib; sourceTree = "<group>"; };
|
||||
D57920A6292F4763004DBD4F /* QrCodeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QrCodeViewController.h; sourceTree = "<group>"; };
|
||||
D57920A7292F4763004DBD4F /* QrCodeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QrCodeViewController.m; sourceTree = "<group>"; };
|
||||
D589C9B928B62D93002CAA34 /* cacert.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cacert.pem; sourceTree = "<group>"; };
|
||||
D59AB422292DBABA00714392 /* Unity-iPhone.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "Unity-iPhone.entitlements"; path = "Unity-iPhone/Unity-iPhone.entitlements"; sourceTree = "<group>"; };
|
||||
D59AB423292DBACE00714392 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||
@ -371,6 +386,14 @@
|
||||
D59AB42E292E250500714392 /* UICKeyChainStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UICKeyChainStore.m; sourceTree = "<group>"; };
|
||||
D59AB431292E26B600714392 /* DataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataManager.h; sourceTree = "<group>"; };
|
||||
D59AB432292E26CE00714392 /* DataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DataManager.m; sourceTree = "<group>"; };
|
||||
D59AB4A4292F325E00714392 /* LBXPermission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermission.h; sourceTree = "<group>"; };
|
||||
D59AB4A5292F325E00714392 /* LBXPermissionCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionCamera.h; sourceTree = "<group>"; };
|
||||
D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionSetting.m; sourceTree = "<group>"; };
|
||||
D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionPhotos.m; sourceTree = "<group>"; };
|
||||
D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionCamera.m; sourceTree = "<group>"; };
|
||||
D59AB4A9292F325E00714392 /* LBXPermission.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermission.m; sourceTree = "<group>"; };
|
||||
D59AB4AA292F325E00714392 /* LBXPermissionPhotos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionPhotos.h; sourceTree = "<group>"; };
|
||||
D59AB4AB292F325E00714392 /* LBXPermissionSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionSetting.h; sourceTree = "<group>"; };
|
||||
D5AB1D2828BF782200AA6AFA /* QRCodeReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderView.h; sourceTree = "<group>"; };
|
||||
D5AB1D2928BF782200AA6AFA /* QRToggleTorchButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRToggleTorchButton.m; sourceTree = "<group>"; };
|
||||
D5AB1D2A28BF782200AA6AFA /* QRCodeReaderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderDelegate.h; sourceTree = "<group>"; };
|
||||
@ -759,6 +782,20 @@
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D57920A3292F45D3004DBD4F /* qr */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D579209C292F3C94004DBD4F /* LBXScanNative.h */,
|
||||
D579209E292F3C94004DBD4F /* LBXScanNative.m */,
|
||||
D57920A0292F3D28004DBD4F /* LBXScanTypes.h */,
|
||||
D57920A1292F3D28004DBD4F /* LBXScanTypes.m */,
|
||||
D57920A6292F4763004DBD4F /* QrCodeViewController.h */,
|
||||
D57920A7292F4763004DBD4F /* QrCodeViewController.m */,
|
||||
D57920A4292F4738004DBD4F /* QrCodeViewController.xib */,
|
||||
);
|
||||
name = qr;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D59AB434292E389E00714392 /* KeyChain */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -770,6 +807,21 @@
|
||||
path = KeyChain;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D59AB4A3292F325E00714392 /* permission */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D59AB4A4292F325E00714392 /* LBXPermission.h */,
|
||||
D59AB4A5292F325E00714392 /* LBXPermissionCamera.h */,
|
||||
D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */,
|
||||
D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */,
|
||||
D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */,
|
||||
D59AB4A9292F325E00714392 /* LBXPermission.m */,
|
||||
D59AB4AA292F325E00714392 /* LBXPermissionPhotos.h */,
|
||||
D59AB4AB292F325E00714392 /* LBXPermissionSetting.h */,
|
||||
);
|
||||
path = permission;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D5AB1D2728BF782200AA6AFA /* QRCodeReaderViewController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -904,6 +956,7 @@
|
||||
D5F2CFAB287BF3BD003C2B62 /* Classes_cocos */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D59AB4A3292F325E00714392 /* permission */,
|
||||
D5F2CFAE287BF3BD003C2B62 /* NativeConfig.h */,
|
||||
D5F2CFAC287BF3BD003C2B62 /* AppDelegate.h */,
|
||||
D5F2CFAF287BF3BD003C2B62 /* AppDelegate.mm */,
|
||||
@ -913,6 +966,7 @@
|
||||
D5F2D104287C12DD003C2B62 /* JcWallet.mm */,
|
||||
D5538BA4287E9908000BDFB6 /* WalletEvent.h */,
|
||||
D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */,
|
||||
D57920A3292F45D3004DBD4F /* qr */,
|
||||
D59AB434292E389E00714392 /* KeyChain */,
|
||||
);
|
||||
path = Classes_cocos;
|
||||
@ -1083,6 +1137,7 @@
|
||||
7885412B8F5A921FCB052FCC /* LaunchScreen-iPhoneLandscape.png in Resources */,
|
||||
B39C4391A8C22B442413FE00 /* LaunchScreen-iPad.xib in Resources */,
|
||||
C7134CE09546D0C147DAA3D3 /* LaunchScreen-iPad.png in Resources */,
|
||||
D57920A5292F4738004DBD4F /* QrCodeViewController.xib in Resources */,
|
||||
D5F2CED6287BE9C4003C2B62 /* Data in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -1177,6 +1232,7 @@
|
||||
D5F2CFA6287BEC0D003C2B62 /* Bulk_netstandard_0.cpp in Sources */,
|
||||
D5F2CF53287BEC0D003C2B62 /* GenericMethods0.cpp in Sources */,
|
||||
D5AB1D3628BF782300AA6AFA /* QRCodeReaderView.m in Sources */,
|
||||
D59AB4AC292F325E00714392 /* LBXPermissionSetting.m in Sources */,
|
||||
D5F2CF95287BEC0D003C2B62 /* Bulk_mscorlib_12.cpp in Sources */,
|
||||
D5F2CF87287BEC0D003C2B62 /* Bulk_UnityEngine.CoreModule_1.cpp in Sources */,
|
||||
D82DCFC30E8000A5005D6AD8 /* main.mm in Sources */,
|
||||
@ -1237,6 +1293,7 @@
|
||||
D5F2CF49287BEC0D003C2B62 /* UnityICallRegistration.cpp in Sources */,
|
||||
D5F2CF65287BEC0D003C2B62 /* Bulk_mscorlib_5.cpp in Sources */,
|
||||
848031E11C5160D700FCEAB7 /* UnityReplayKit_Scripting.mm in Sources */,
|
||||
D59AB4AD292F325E00714392 /* LBXPermissionPhotos.m in Sources */,
|
||||
D5F2CF94287BEC0D003C2B62 /* Bulk_Generics_9.cpp in Sources */,
|
||||
D5F2CF52287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_16Table.cpp in Sources */,
|
||||
D5F2CF91287BEC0D003C2B62 /* Bulk_mscorlib_10.cpp in Sources */,
|
||||
@ -1271,6 +1328,7 @@
|
||||
D59AB42F292E250500714392 /* UICKeyChainStore.m in Sources */,
|
||||
D5F2CF90287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_6Table.cpp in Sources */,
|
||||
D5F2CFA8287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_13Table.cpp in Sources */,
|
||||
D59AB4AF292F325E00714392 /* LBXPermission.m in Sources */,
|
||||
D5F2CF5C287BEC0D003C2B62 /* Bulk_Generics_7.cpp in Sources */,
|
||||
8A793A091ED43EE100B44EF1 /* UnityViewControllerBase+tvOS.mm in Sources */,
|
||||
D5F2CF58287BEC0D003C2B62 /* Il2CppGenericMethodPointerTable.cpp in Sources */,
|
||||
@ -1282,8 +1340,10 @@
|
||||
D5F2CFA2287BEC0D003C2B62 /* Bulk_System.Globalization.Extensions_0.cpp in Sources */,
|
||||
D5F2CF77287BEC0D003C2B62 /* Bulk_Generics_10.cpp in Sources */,
|
||||
D5F2CF44287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_9Table.cpp in Sources */,
|
||||
D57920A8292F4763004DBD4F /* QrCodeViewController.m in Sources */,
|
||||
D5F2CF6B287BEC0D003C2B62 /* Bulk_mscorlib_3.cpp in Sources */,
|
||||
D5F2CF92287BEC0D003C2B62 /* Bulk_System.Configuration_0.cpp in Sources */,
|
||||
D57920A2292F3D28004DBD4F /* LBXScanTypes.m in Sources */,
|
||||
D5AB1D3728BF782300AA6AFA /* QRCodeReader.m in Sources */,
|
||||
D5F2CF9D287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_19Table.cpp in Sources */,
|
||||
D5F2CF61287BEC0D003C2B62 /* Bulk_mscorlib_6.cpp in Sources */,
|
||||
@ -1292,6 +1352,7 @@
|
||||
D5F2CF62287BEC0D003C2B62 /* Bulk_mscorlib_7.cpp in Sources */,
|
||||
8A4815C117A28E7F003FBFD5 /* UnityAppController+ViewHandling.mm in Sources */,
|
||||
D5F2D106287C12DD003C2B62 /* JcWallet.mm in Sources */,
|
||||
D579209F292F3C94004DBD4F /* LBXScanNative.m in Sources */,
|
||||
D5F2CF8B287BEC0D003C2B62 /* Bulk_System.Diagnostics.StackTrace_0.cpp in Sources */,
|
||||
D5F2CF63287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_10Table.cpp in Sources */,
|
||||
D5F2CF88287BEC0D003C2B62 /* Bulk_UnityEngine.UIModule_0.cpp in Sources */,
|
||||
@ -1315,6 +1376,7 @@
|
||||
D5F2CF69287BEC0D003C2B62 /* Bulk_mscorlib_1.cpp in Sources */,
|
||||
D5F2CF55287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_23Table.cpp in Sources */,
|
||||
D5F2CF66287BEC0D003C2B62 /* Bulk_mscorlib_4.cpp in Sources */,
|
||||
D59AB4AE292F325E00714392 /* LBXPermissionCamera.m in Sources */,
|
||||
AAC3E38D1A68945900F6174A /* RegisterFeatures.cpp in Sources */,
|
||||
84DC28F61C5137FE00BC67D7 /* UnityReplayKit.mm in Sources */,
|
||||
D5F2CF73287BEC0D003C2B62 /* Bulk_System_0.cpp in Sources */,
|
||||
@ -1381,6 +1443,7 @@
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = YES;
|
||||
GCC_ENABLE_CPP_RTTI = YES;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = Classes/Prefix.pch;
|
||||
@ -1468,6 +1531,7 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = YES;
|
||||
GCC_ENABLE_CPP_RTTI = YES;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = Classes/Prefix.pch;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@ -1683,6 +1747,7 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = YES;
|
||||
GCC_ENABLE_CPP_RTTI = YES;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = Classes/Prefix.pch;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@ -1840,6 +1905,7 @@
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = YES;
|
||||
GCC_ENABLE_CPP_RTTI = YES;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = Classes/Prefix.pch;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
|
@ -12,11 +12,11 @@
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9"
|
||||
endingColumnNumber = "9"
|
||||
startingLineNumber = "133"
|
||||
endingLineNumber = "133"
|
||||
landmarkName = "-refreshTokenID:funid:"
|
||||
startingColumnNumber = "11"
|
||||
endingColumnNumber = "11"
|
||||
startingLineNumber = "107"
|
||||
endingLineNumber = "107"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
@ -30,9 +30,9 @@
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "131"
|
||||
endingLineNumber = "131"
|
||||
landmarkName = "-refreshTokenID:funid:"
|
||||
startingLineNumber = "105"
|
||||
endingLineNumber = "105"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
@ -46,28 +46,12 @@
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "133"
|
||||
endingLineNumber = "133"
|
||||
landmarkName = "-refreshTokenID:funid:"
|
||||
startingLineNumber = "107"
|
||||
endingLineNumber = "107"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "15F1FD11-897D-4AA2-89F0-86DCB06070A1"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "189"
|
||||
endingLineNumber = "189"
|
||||
landmarkName = "nativeCallBack(funId, methodName, cparams)"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
@ -78,9 +62,9 @@
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "132"
|
||||
endingLineNumber = "132"
|
||||
landmarkName = "-refreshTokenID:funid:"
|
||||
startingLineNumber = "106"
|
||||
endingLineNumber = "106"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
@ -94,25 +78,9 @@
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "138"
|
||||
endingLineNumber = "138"
|
||||
landmarkName = "-signWithGoogle:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "4D1CEFCB-9F08-4069-BC1B-9139709C217E"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "135"
|
||||
endingLineNumber = "135"
|
||||
landmarkName = "JcWallet::runJsMethod(data)"
|
||||
startingLineNumber = "112"
|
||||
endingLineNumber = "112"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
@ -132,5 +100,101 @@
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "47347B45-DB23-4252-AFCD-8D070482488B"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "65"
|
||||
endingLineNumber = "65"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "DF8812E4-AA7D-42CD-BA48-816CB6377C98"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "70"
|
||||
endingLineNumber = "70"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "6DA3708B-7F80-4969-83A7-4AE84264C340"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/UIViewController+Wallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "64"
|
||||
endingLineNumber = "64"
|
||||
landmarkName = "-scanQRCode:title:"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "5228CC88-A530-4590-BFE9-CB7361B45F34"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "205"
|
||||
endingLineNumber = "205"
|
||||
landmarkName = "runWalletMethod(funId, methodName, paramCount, paramList)"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "DED33FE0-B995-4059-9A5A-1A41F1F988B4"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "169"
|
||||
endingLineNumber = "169"
|
||||
landmarkName = "JcWallet::tickRun()"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "4418B859-58DC-425E-B856-48D07E6F9315"
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes_cocos/JcWallet.mm"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "272"
|
||||
endingLineNumber = "272"
|
||||
landmarkName = "jsb_wallet_callback(s)"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
@ -1,3 +1,4 @@
|
||||
window.self = window.self || window;
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
(function (global){
|
||||
"use strict";
|
||||
|
28
js/main.js
@ -125,6 +125,7 @@ function changeChain(funId, chainId) {
|
||||
* @param {string} tips: tips message when sign
|
||||
*/
|
||||
function loginSign(funId, nonce, tips) {
|
||||
console.log('login sign: ' + funId)
|
||||
jc.wallet
|
||||
.loginSign(nonce, tips)
|
||||
.then((result) => {
|
||||
@ -163,18 +164,21 @@ function createAccount(funId) {
|
||||
* @return {string} account actived
|
||||
*/
|
||||
function importAccount(funId, privateKey) {
|
||||
try {
|
||||
let address = jc.wallet.importAccount(privateKey);
|
||||
return JSON.stringify({
|
||||
errcode: 0,
|
||||
data: address,
|
||||
});
|
||||
} catch (err) {
|
||||
return JSON.stringify({
|
||||
errcode: 1,
|
||||
errmsg: err,
|
||||
});
|
||||
}
|
||||
console.log('importAccount: ' + funId);
|
||||
// jsb.scanQRCode(funId, '111');
|
||||
jsb.showQRCode('00123', '0x12312312313123123123', 'CEBG RECOVERY KEY', '0x1231231231321231');
|
||||
// try {
|
||||
// let address = jc.wallet.importAccount(privateKey);
|
||||
// return JSON.stringify({
|
||||
// errcode: 0,
|
||||
// data: address,
|
||||
// });
|
||||
// } catch (err) {
|
||||
// return JSON.stringify({
|
||||
// errcode: 1,
|
||||
// errmsg: err,
|
||||
// });
|
||||
// }
|
||||
// jc.wallet.erc20Standard.transfer({
|
||||
// address: '0xC76c692450d6221A8B1E035CB8bdB639bC60658D',
|
||||
// from: '0x50A8e60041A206AcaA5F844a1104896224be6F39',
|
||||
|