iOS 二维码窗口

iOS 学习日志 : iOS原生二维码的扫描以及限定扫描范围,有需要的朋友可以参考下。



现在的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 移除动画,并把扫描框从当前视图中移除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值