利用系统AV框架制作实现扫一扫功能(一行代码搞定)
本帖最后由 Sian 于 2015-12-3 17:55 编辑1、先上图看看效果
2、设计思路
2.1、利用AVCaptureMetadataOutput固有的输出属性,能够输出二维码及条形码的解析结果
2.2、利用Quartz 2D绘出基本扫描界面,结合动画效果,简单又高效!2.3、只需两个类,一个控制器,一个视图:SAScanCtrl SAScan
2.3、其他内容在代码中给出相关注释说明
3、部分代码
SAScanCtrl.h
//
//SAScanCtrl.h
//
//
//Created by 余西安 on 15/12/3.
//Copyright © 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void (^SAScanBlock)(NSString *string);
@interface SAScanCtrl : UIViewController
@property (nonatomic, copy) SAScanBlock block;
- (instancetype)initWithBlock:(SAScanBlock)block;
@end
SAScanCtrl.m//
//SAScanCtrl.m
//
//
//Created by 余西安 on 15/12/3.
//Copyright © 2015年 Sian. All rights reserved.
//
#import "SAScanCtrl.h"
#import "SAScan.h"
#import <AVFoundation/AVFoundation.h>
@interface SAScanCtrl ()<AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVAudioPlayer *player;
@property (nonatomic, strong) SAScan *scan;
@end
@implementation SAScanCtrl
- (instancetype)initWithBlock:(SAScanBlock)block
{
if (self = ){
self.block = block;
}
return self;
}
- (void)viewDidLoad
{
;
;
AVCaptureDevice *device = ;
AVCaptureDeviceInput *input = ;
AVCaptureMetadataOutput *output = [init];
; // 设置代理 在主线程里刷新
;
//初始化链接对象
self.session = [ init];
;
;
;
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
];
AVCaptureVideoPreviewLayer *layer = ;
layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
layer.frame = self.view.bounds;
;
self.scan = [ initWithFrame:self.view.bounds];
;
NSURL *url = pathForResource:@"scan" ofType:@"mp3"]];
self.player = [ initWithContentsOfURL:url error:nil];
UIBarButtonItem *item = [ initWithTitle:@"重试" style:UIBarButtonItemStylePlain target:self action:@selector(startRunning)];
;
}
- (void)viewWillAppear:(BOOL)animated
{
;
;
}
- (void)viewDidAppear:(BOOL)animated
{
;
;
}
- (void)viewWillDisappear:(BOOL)animated
{
;
;
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects.count > 0){
AVMetadataMachineReadableCodeObject *metadataObject = ;
;
;
;
if (self.block) self.block(metadataObject.stringValue);
;
;
}
}
- (void)startRunning
{
;
;
}
@end
Scan.h//
//SAScan.h
//
//
//Created by 余西安 on 15/12/3.
//Copyright © 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAScan : UIView
@property (nonatomic, strong) UIImageView *scanLine;
- (void)startAnimation;
- (void)stopAnimation;
@end
Scan.m//
//SAScan.m
//
//
//Created by 余西安 on 15/12/3.
//Copyright © 2015年 Sian. All rights reserved.
//
#import "SAScan.h"
@implementation SAScan
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = ){
self.backgroundColor = ;
UIImage *line = ;
self.scanLine = [ initWithImage:line];
;
;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
//非扫码区域半透明
{
CGFloat w = self.bounds.size.width * 0.7;
CGFloat x = (self.bounds.size.width - w) * 0.5;
CGFloat y = (self.bounds.size.height - w) * 0.5;
{ // 外围区域填充半透明黑色
// 设置非识别区域颜色
CGContextSetRGBFillColor(context, 0, 0, 0, 0.6);
// 扫码区域上面填充
CGRect rect = CGRectMake(0, 0, self.frame.size.width, y);
CGContextFillRect(context, rect);
// 扫码区域左边填充
rect = CGRectMake(0, y, x, w);
CGContextFillRect(context, rect);
// 扫码区域右边填充
rect = CGRectMake(x + w, y, x, w);
CGContextFillRect(context, rect);
// 扫码区域下面填充
rect = CGRectMake(0, y + w, self.frame.size.width, self.frame.size.height - y - w);
CGContextFillRect(context, rect);
}
{ // 中间可视区域画边框
UIColor *whiteColor = ;
CGContextSetStrokeColorWithColor(context, whiteColor.CGColor);
CGContextSetLineWidth(context, 1);
CGContextAddRect(context, CGRectMake(x, y, w, w));
CGContextStrokePath(context);
}
{ // 中间可视区域画角框
CGFloat lineWidth = 4.0f;
CGFloat angleWidth = 15.0f;
UIColor *greenColor = ;
CGContextSetLineWidth(context, lineWidth);
CGContextSetStrokeColorWithColor(context, greenColor.CGColor);
// 左上角
CGContextMoveToPoint(context, x, y + angleWidth);
CGContextAddLineToPoint(context, x, y);
CGContextAddLineToPoint(context, x + angleWidth, y);
// 右上角
CGContextMoveToPoint(context, x + w - angleWidth, y);
CGContextAddLineToPoint(context, x + w, y);
CGContextAddLineToPoint(context, x + w, y + angleWidth);
// 右下角
CGContextMoveToPoint(context, x + w, y + w - angleWidth);
CGContextAddLineToPoint(context, x + w, y + w);
CGContextAddLineToPoint(context, x + w - angleWidth, y + w);
// 左下角
CGContextMoveToPoint(context, x + angleWidth, y + w);
CGContextAddLineToPoint(context, x, y + w);
CGContextAddLineToPoint(context, x, y + w - angleWidth);
}
CGContextStrokePath(context);
}
}
- (void)layoutSubviews
{
;
CGFloat width = self.bounds.size.width;
CGFloat y = (self.bounds.size.height - width * 0.7) * 0.5;
self.scanLine.frame = CGRectMake(0, y, width, 12);
}
- (void)startAnimation
{
CGFloat width = self.bounds.size.width;
CGFloat y = (self.bounds.size.height - width * 0.7) * 0.5;
self.scanLine.frame = CGRectMake(0, y, width, 12);
self.scanLine.hidden = NO;
[UIView animateWithDuration:2.5 delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
self.scanLine.center = CGPointMake(width * 0.5, y + width * 0.7);
} completion:^(BOOL finished) {
if (finished) self.scanLine.center = CGPointMake(width * 0.5, y);
}];
}
- (void)stopAnimation
{
self.scanLine.hidden = YES;
;
}
@end
4、使用只需一行代码:
SAScanCtrl *scan = [ initWithBlock:^(NSString *string) { [[ initWithTitle:nil message:string delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show]; }]; UINavigationController *nav = [ initWithRootViewController:scan]; ;
5、Demo下载
**** Hidden Message *****
二维码扫描,,看看,,谢谢
页:
[1]