iOS 学习日志 : iOS原生二维码的扫描以及限定扫描范围

来源:互联网 发布:要怎么加盟农村淘宝 编辑:程序博客网 时间:2024/06/03 20:26

现在的app多少都会加入二维码扫描功能,方便快捷,开发中常常会碰到这样的需求.

定义会话和输出流对象

@property (nonatomic) AVCaptureSession *captureSession;@property (nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
// 获取 AVCaptureDevice 实例    NSError * error;    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];    // 初始化输入流    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];    if (!input) {        NSLog(@"%@", [error localizedDescription]);        return NO;    }    // 创建会话    _captureSession = [[AVCaptureSession alloc] init];    // 添加输入流    [_captureSession addInput:input];    // 初始化输出流    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];    // 添加输出流    [_captureSession addOutput:captureMetadataOutput];    // 创建dispatch queue.    dispatch_queue_t dispatchQueue;    dispatchQueue = dispatch_queue_create(kScanQRCodeQueueName, NULL);    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];    // 设置数据类型 AVMetadataObjectTypeQRCode    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];    // 创建输出对象    _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];    [_videoPreviewLayer setFrame:self.view.bounds];    [self.view.layer addSublayer:_videoPreviewLayer];    // 开始会话    [_captureSession startRunning];

这里准备工作就做完了,在startRunning后就会开启二维码的扫描,然后遵守AVCaptureMetadataOutputObjectsDelegate代理 ,在代理方法中处理扫码获得的数据

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects      fromConnection:(AVCaptureConnection *)connection{    if (metadataObjects != nil && [metadataObjects count] > 0) {        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];        NSString *result;        [_captureSession stopRunning];        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {            result = metadataObj.stringValue;        } else {            NSLog(@"不是二维码");        }    }}

这样最基础的二维码扫描就做完了,但是用户体验并不好,因为默认的是全屏扫描,而且原生的二维码扫描很快,容易误操作,影响用户体验.

所以我们需要限定扫描的范围,AVCaptureMetadataOutput 有对应的属性设置扫描范围,但是它的坐标系有些特殊 并不是常见的(x,y,width,height)而是(y,x,height,width),所以就需要将坐标翻转过来,下面是一个左右间距各50,居中的正方形扫描框,那么就将扫描范围限定在这个扫描框里。
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[captureMetadataOutput setRectOfInterest:CGRectMake(([UIScreen mainScreen].bounds.size.height/2-([UIScreen mainScreen].bounds.size.width-100)/2)/
[UIScreen mainScreen].bounds.size.height,50/[UIScreen mainScreen].bounds.size.width, ([UIScreen mainScreen].bounds.size.width-100)/[UIScreen mainScreen].bounds.size.height, ([UIScreen mainScreen].bounds.size.width-100)/[UIScreen mainScreen].bounds.size.width)];

最后嘛 可以利用view的动画来完成扫描框的线性”扫描”,提升用户体验

下面是利用masory约束的一个 左右间距50并居中的扫描框,然后利用动画完成线性的扫描,欺骗用户…….0.0

UIView * anniView= [[UIView alloc]init];    anniView.tag = 111;    [self.view addSubview:anniView];    [anniView mas_makeConstraints:^(MASConstraintMaker *make) {        make.centerX.equalTo(self.view.mas_centerX);        make.centerY.equalTo(self.view.mas_centerY);        make.left.equalTo(self.view).with.offset(50);        make.right.equalTo(self.view).with.offset(-50);        make.width.equalTo(anniView.mas_height);    }];    //扫描框    UIImageView * imageView = [[UIImageView alloc]init];    [anniView addSubview:imageView];    [imageView mas_makeConstraints:^(MASConstraintMaker *make) {        make.edges.equalTo(anniView).insets(UIEdgeInsetsMake(0, 0, 0, 0));    }];    imageView.image = [UIImage imageNamed:@"cornround"];    //扫描线    UIImageView * line = [[UIImageView alloc]init];    [anniView insertSubview:line aboveSubview:imageView];    line.backgroundColor = [UIColor clearColor];    line.image = [UIImage imageNamed:@"line"];    [line mas_makeConstraints:^(MASConstraintMaker *make) {        make.left.equalTo(anniView).with.offset(0);        make.right.equalTo(anniView).with.offset(0);        make.top.equalTo(anniView).with.offset(0);        make.height.equalTo(@2);    }];    CABasicAnimation *animationMove = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];    [animationMove setFromValue:@(0)];    [animationMove setToValue:@([UIScreen mainScreen].bounds.size.width-102)];    animationMove.duration = 5.0f;    animationMove.delegate = self;    animationMove.repeatCount  = OPEN_MAX;    animationMove.removedOnCompletion = NO;    animationMove.fillMode = kCAFillModeForwards;    animationMove.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];    [line.layer addAnimation:animationMove forKey:animationKey];

最后在扫码获取到数据之后,停止扫描.并根据tag值获取UIImageView 移除动画,并把扫描框从当前视图中移除

3 0
原创粉丝点击