扫一扫功能很常见, 也很实用, 自己没事写了一下, 以后项目一劳永逸了, 本文使用的是系统的AVFoundation框架, 非常方便.
下面直接上代码:
#pragma mark - - - 二维码扫描
- (void)setupScanningQRCode {
// 1、 获取摄像设备
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// 2、 创建输入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
// 3、 创建输出流
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
// 4、设置代理 在主线程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
// 设置扫描范围(每一个取值0~1,以屏幕右上角为坐标原点)
output.rectOfInterest = CGRectMake(0.15, 0.24, 0.7, 0.52);
// 5、 初始化链接对象(会话对象)
self.session = [[AVCaptureSession alloc] init];
//高质量采集率
[_session setSessionPreset:AVCaptureSessionPresetHigh];
// 5.1 添加会话输入
[_session addInput:input];
// 5.2 添加会话输出
[_session addOutput:output];
// 6、设置输出数据类型,需要将元数据输出添加到会话后,才能指定元数据类型,否则会报错
// 设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
// 7、实例化预览图层, 传递_session是为了告诉图层将来显示什么内容
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
_previewLayer.frame = self.view.layer.bounds;
// 8、将图层插入当前视图
[self.view.layer insertSublayer:_previewLayer atIndex:0];
// 9、启动会话
[_session startRunning];
}
然后处理扫描结果:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
// 会频繁的扫描,调用代理方法
// 1. 如果扫描完成,停止会话
[self.session stopRunning];
// 2. 删除预览图层
[self.previewLayer removeFromSuperlayer];
// 3. 设置界面显示扫描结果
if (metadataObjects.count > 0) {
AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
if ([obj.stringValue hasPrefix:@"http"]) {
// 提示:如果需要对url或者名片等信息进行扫描,可以在此进行扩展!
NSLog(@"扫描网址为----------%@", obj.stringValue);
} else { // 扫描结果为条形码
NSLog(@"扫描条形码为----------%@", obj.stringValue);
}
}
}
再然后就是处理框框周围的区域, 可以加个半透明的遮罩, 扫描区域的四个角, 加上边框, 可以加个打开手电筒的按钮, 加一根扫描的线, 加上动画, 上下扫动, 加一些提示语句, 就大功告成了!
下面是遮罩的部分代码:
//打开手电筒
- (void)turnOnLight:(BOOL)on {
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([_device hasTorch]) {
[_device lockForConfiguration:nil];
if (on) {
[_device setTorchMode:AVCaptureTorchModeOn];
} else {
[_device setTorchMode: AVCaptureTorchModeOff];
}
[_device unlockForConfiguration];
}
}
// 创建扫描边框
- (void)setupScanningQRCodeEdging {
// 扫描内容的创建
UIView *scanContentView = [[UIView alloc] init];
CGFloat scanContentViewX = scanContent_X;
CGFloat scanContentViewY = scanContent_Y;
CGFloat scanContentViewW = self.frame.size.width - 2 * scanContent_X;
CGFloat scanContentViewH = scanContentViewW;
scanContentView.frame = CGRectMake(scanContentViewX, scanContentViewY, scanContentViewW, scanContentViewH);
scanContentView.layer.borderColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6].CGColor;
scanContentView.layer.borderWidth = 0.7;
scanContentView.backgroundColor = [UIColor clearColor];
[self.basedLayer addSublayer:scanContentView.layer];
// 扫描动画添加
self.animation_line = [[UIImageView alloc] init];
_animation_line.image = [UIImage imageNamed:@"QRCodeLine"];
_animation_line.frame = CGRectMake(scanContent_X * 0.5, scanContentViewY, self.frame.size.width - scanContent_X , animation_line_H);
[self.basedLayer addSublayer:_animation_line.layer];
// 添加定时器
self.timer =[NSTimer scheduledTimerWithTimeInterval:timer_animation_Duration target:self selector:@selector(animation_line_action) userInfo:nil repeats:YES];
#pragma mark - - - 扫描外部View的创建
// 顶部View的创建
UIView *top_View = [[UIView alloc] init];
CGFloat top_ViewX = 0;
CGFloat top_ViewY = 0;
CGFloat top_ViewW = self.frame.size.width;
CGFloat top_ViewH = scanContentViewY;
top_View.frame = CGRectMake(top_ViewX, top_ViewY, top_ViewW, top_ViewH);
top_View.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:scanBorderOutsideViewAlpha];
[self addSubview:top_View];
// 左侧View的创建
UIView *left_View = [[UIView alloc] init];
CGFloat left_ViewX = 0;
CGFloat left_ViewY = scanContentViewY;
CGFloat left_ViewW = scanContent_X;
CGFloat left_ViewH = scanContentViewH;
left_View.frame = CGRectMake(left_ViewX, left_ViewY, left_ViewW, left_ViewH);
left_View.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:scanBorderOutsideViewAlpha];
[self addSubview:left_View];
// 右侧View的创建
UIView *right_View = [[UIView alloc] init];
CGFloat right_ViewX = CGRectGetMaxX(scanContentView.frame);
CGFloat right_ViewY = scanContentViewY;
CGFloat right_ViewW = scanContent_X;
CGFloat right_ViewH = scanContentViewH;
right_View.frame = CGRectMake(right_ViewX, right_ViewY, right_ViewW, right_ViewH);
right_View.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:scanBorderOutsideViewAlpha];
[self addSubview:right_View];
// 下面View的创建
UIView *bottom_View = [[UIView alloc] init];
CGFloat bottom_ViewX = 0;
CGFloat bottom_ViewY = CGRectGetMaxY(scanContentView.frame);
CGFloat bottom_ViewW = self.frame.size.width;
CGFloat bottom_ViewH = self.frame.size.height - bottom_ViewY;
bottom_View.frame = CGRectMake(bottom_ViewX, bottom_ViewY, bottom_ViewW, bottom_ViewH);
bottom_View.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:scanBorderOutsideViewAlpha];
[self addSubview:bottom_View];
// 提示Label
UILabel *promptLabel = [[UILabel alloc] init];
promptLabel.backgroundColor = [UIColor clearColor];
CGFloat promptLabelX = 0;
CGFloat promptLabelY = scanContent_X * 0.5;
CGFloat promptLabelW = self.frame.size.width;
CGFloat promptLabelH = 25;
promptLabel.frame = CGRectMake(promptLabelX, promptLabelY, promptLabelW, promptLabelH);
promptLabel.textAlignment = NSTextAlignmentCenter;
promptLabel.font = [UIFont boldSystemFontOfSize:13.0];
promptLabel.textColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6];
promptLabel.text = @"将二维码/条码放入框内, 即可自动扫描";
[bottom_View addSubview:promptLabel];
// 添加闪光灯按钮
UIButton *light_button = [[UIButton alloc] init];
CGFloat light_buttonX = 0;
CGFloat light_buttonY = CGRectGetMaxY(promptLabel.frame) + scanContent_X * 0.5;
CGFloat light_buttonW = self.frame.size.width;
CGFloat light_buttonH = 25;
light_button.frame = CGRectMake(light_buttonX, light_buttonY, light_buttonW, light_buttonH);
[light_button setTitle:@"打开照明灯" forState:UIControlStateNormal];
[light_button setTitle:@"关闭照明灯" forState:UIControlStateSelected];
[light_button setTitleColor:promptLabel.textColor forState:(UIControlStateNormal)];
light_button.titleLabel.font = [UIFont systemFontOfSize:17];
[light_button addTarget:self action:@selector(light_buttonAction:) forControlEvents:UIControlEventTouchUpInside];
[bottom_View addSubview:light_button];
#pragma mark - - - 扫描边角imageView的创建
// 左上侧的image
CGFloat margin = 7;
UIImage *left_image = [UIImage imageNamed:@"TopLeft"];
UIImageView *left_imageView = [[UIImageView alloc] init];
CGFloat left_imageViewX = CGRectGetMinX(scanContentView.frame) - left_image.size.width * 0.5 + margin;
CGFloat left_imageViewY = CGRectGetMinY(scanContentView.frame) - left_image.size.width * 0.5 + margin;
CGFloat left_imageViewW = left_image.size.width;
CGFloat left_imageViewH = left_image.size.height;
left_imageView.frame = CGRectMake(left_imageViewX, left_imageViewY, left_imageViewW, left_imageViewH);
left_imageView.image = left_image;
[self.basedLayer addSublayer:left_imageView.layer];
// 右上侧的image
UIImage *right_image = [UIImage imageNamed:@"TopRight"];
UIImageView *right_imageView = [[UIImageView alloc] init];
CGFloat right_imageViewX = CGRectGetMaxX(scanContentView.frame) - right_image.size.width * 0.5 - margin;
CGFloat right_imageViewY = left_imageView.frame.origin.y;
CGFloat right_imageViewW = left_image.size.width;
CGFloat right_imageViewH = left_image.size.height;
right_imageView.frame = CGRectMake(right_imageViewX, right_imageViewY, right_imageViewW, right_imageViewH);
right_imageView.image = right_image;
[self.basedLayer addSublayer:right_imageView.layer];
// 左下侧的image
UIImage *left_image_down = [UIImage imageNamed:@"BottomLeft"];
UIImageView *left_imageView_down = [[UIImageView alloc] init];
CGFloat left_imageView_downX = left_imageView.frame.origin.x;
CGFloat left_imageView_downY = CGRectGetMaxY(scanContentView.frame) - left_image_down.size.width * 0.5 - margin;
CGFloat left_imageView_downW = left_image.size.width;
CGFloat left_imageView_downH = left_image.size.height;
left_imageView_down.frame = CGRectMake(left_imageView_downX, left_imageView_downY, left_imageView_downW, left_imageView_downH);
left_imageView_down.image = left_image_down;
[self.basedLayer addSublayer:left_imageView_down.layer];
// 右下侧的image
UIImage *right_image_down = [UIImage imageNamed:@"BottomRight"];
UIImageView *right_imageView_down = [[UIImageView alloc] init];
CGFloat right_imageView_downX = right_imageView.frame.origin.x;
CGFloat right_imageView_downY = left_imageView_down.frame.origin.y;
CGFloat right_imageView_downW = left_image.size.width;
CGFloat right_imageView_downH = left_image.size.height;
right_imageView_down.frame = CGRectMake(right_imageView_downX, right_imageView_downY, right_imageView_downW, right_imageView_downH);
right_imageView_down.image = right_image_down;
[self.basedLayer addSublayer:right_imageView_down.layer];
}
大功告成, 是不是很简单, 以后项目中遇到把文件直接拖进去就行了.
下面附上完整代码Github地址.
如果觉得有用, 记得点收藏哟~~~~
网友评论