Sian 发表于 2015-12-3 17:54:18

利用系统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 *****

豆丁00544 发表于 2015-12-23 15:57:09

二维码扫描,,看看,,谢谢
页: [1]
查看完整版本: 利用系统AV框架制作实现扫一扫功能(一行代码搞定)