美文网首页iOS开发IOSiOS开发 技术集锦
iOS7 系统二维码扫描 (设置扫描区域、中空区域)

iOS7 系统二维码扫描 (设置扫描区域、中空区域)

作者: loongod | 来源:发表于2015-11-12 12:30 被阅读5551次

    显示出来扫描二维码的界面,很简单:

    AVCaptureDevice  *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil];

    self.captureOutput = [[AVCaptureMetadataOutput alloc] init];

    [_captureOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

    self.captureSession = [[AVCaptureSession alloc] init];

    [_captureSession setSessionPreset:AVCaptureSessionPresetHigh];

    if ([_captureSession canAddInput:captureInput]) {

    [_captureSession addInput:captureInput];

    }

    if ([_captureSession canAddOutput:_captureOutput]) {

    [_captureSession addOutput:_captureOutput];

    }

    _captureOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];

    CGRect rect = CM(30, 100, Screen_Width - 60, 300);

    AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession];

    previewLayer.frame = self.view.bounds;

    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

    [self.view.layer addSublayer:previewLayer];

    [_captureSession startRunning];

    按上述代码设置之后,就可以扫描二维码啦,但是这个是全屏扫描的,貌似无论你的previewLayer的frame设置的多大都是全屏扫描的。

    而且一般设计时,有一个扫描区域之类的,怎么设置呢?

    AVCaptureMetadataOutput 有一个属性 rectOfInterest

    rectOfInterest

    就是设置元数据识别搜索的区域。

    这个属性有点问题,不是普通的CGRect,四个值都需要在0~1之间。

    搜了好久看大家都是试的。最后看到rectOfInterest设置问题这个问题的回答后,才知道的。

    AVCaptureVideoPreviewLayer 有个方法 

    - (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinates

    可以看看这个方法的说明:

    方法说明

    描述就是:把一个在previewlayer坐标系中的rect 转换成 一个在metadataoutputs坐标系中的rect。

    这个方法需要的rect参数是我们系统坐标系中的rect.

    SO 。这就得到了我们需要的rectOfInterest。

    验证:

    我们在 startRuning 之后(这里之前写的是'之前',但是下面的代码是在startRuning之后的)添加如下代码:

    [self.view.layer addSublayer:previewLayer];

    [_captureSession startRunning];

    CGRect intertRect = [previewLayer metadataOutputRectOfInterestForRect:rect];

    CGRect layerRect = [previewLayer rectForMetadataOutputRectOfInterest:intertRect];

    NSLog(@"%@,  %@",NSStringFromCGRect(intertRect),NSStringFromCGRect(layerRect));

    _captureOutput.rectOfInterest = intertRect;

    运行设备是:iPhone6,(375, 667)  设置的rect  (想要的扫描区域)  (30, 100, 315, 300)

    打印结果:

    intertRect  {{0.14992503748125927, 0.080629685157421305}, {0.4497751124437781, 0.8387406296851575}},   

    layerRect {{29.999999999999943, 99.999999999999972}, {315.00000000000006, 300}}

    - (CGRect)rectForMetadataOutputRectOfInterest:(CGRect)rectInMetadataOutputCoordinates

    方法说明

    这个方法是把_captureOutput.rectOfInterest坐标系转成preview layer 的坐标系的rect。

    通过打印数据可以验证成功,真机实验也是正确的。

    补充:设置中间透空区域

    UIView *maskView = [[UIView alloc] initWithFrame:CM(0, 64, Screen_Width, Screen_Height - 64)];

    maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];

    [self.view addSubview:maskView];

    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:CM(0, 0, Screen_Width, Screen_Height)];

    [maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CM(30, 100 - 64, Screen_Width - 60, 300) cornerRadius:1] bezierPathByReversingPath]];

    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

    maskLayer.path = maskPath.CGPath;

    maskView.layer.mask = maskLayer;

    demo地址:github

    相关文章

      网友评论

      • S型身材的猪:还是直接计算吧,如果用metadataOutputRectOfInterestForRect有2点不好:一:必须在startRuning才有效。二:启动二维码扫描会先卡一下再聚焦,体验很差。
      • 嘻嘻嘻小八哥:您好,怎么让条形码进入扫描框的任何位置都可以识别,不需要非得放中间才能扫描上呢?
      • 心猿意码:楼主,设置扫描区域必须在相机被正确设置和运行后设置,因为在运行之前相机的分辨率还没有,你在startRuning 之前调用metadataOutputRectOfInterestForRect:方法返回的值为0,所以你要在startRuning之后调用该方法才有效。
        心猿意码:@loongod 另外一种方法是直接给rectOfInterest属性赋值,这样就不用放在startRuning之后了,不过直接赋值是需要计算的,因为属性rectOfInterest 的CGRect类型是一个比例。
        loongod:谢谢,前面有人提到过,一直忘了改了。再次感谢
      • ctw_native:要在startRuning后调用 metadataOutputRectOfInterestForRect才管用
        donggelaile:太坑了,我也找了半天。楼主更正下吧
        loongod:@一个有前途的男人 这么神奇:scream:
        DDDDeveloper:@chang_the_world 感谢,终于有人提出这个坑了,我被坑了一下午,非常感谢
      • baa0cdc4fdde:加油加油加油
      • 水杯与书桌:非常感谢,帮助很大。哈哈,就是那个扫描区域自己还得做一个界面,开始我以为设定之后直接界面上就有明暗对比了呢。
        loongod:@迅雷粥粥 设置View.layer的mask就行了。
        5429695280dc:请问怎么做那个明暗对比的界面?能不能讲讲思路
        loongod:@水杯与书桌 😋其他的都是需要自己写的。😛

      本文标题:iOS7 系统二维码扫描 (设置扫描区域、中空区域)

      本文链接:https://www.haomeiwen.com/subject/osihhttx.html