iOS实现“摇一摇”与“扫一扫”功能示例代码
时间:2021-09-29 08:49:24|栏目:iOS代码|点击: 次
“摇一摇”功能的实现:
iPhone对 “摇一摇”有很好的支持,总体说来就两步:
在视图控制器中打开接受“摇一摇”的开关;
- (void)viewDidLoad { // 设置允许摇一摇功能 [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES; // 并让自己成为第一响应者 [self becomeFirstResponder]; }
在“摇一摇”触发的制定的方法中实现需要实现的功能(”摇一摇“检测方法)。
// 摇一摇开始摇动 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { NSLog(@"开始摇动"); //添加“摇一摇”动画 [self addAnimations]; //音效 AudioServicesPlaySystemSound (soundID); return; } // “摇一摇”取消摇动 - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event { NSLog(@"取消摇动"); return; } // “摇一摇”摇动结束 - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { if (event.subtype == UIEventSubtypeMotionShake) { // 判断是否是摇动结束 NSLog(@"摇动结束"); } return; }
”摇一摇“的动画效果:
- (void)addAnimations { //音效 AudioServicesPlaySystemSound (soundID); //让上面图片的上下移动 CABasicAnimation *translation2 = [CABasicAnimation animationWithKeyPath:@"position"]; translation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; translation2.fromValue = [NSValue valueWithCGPoint:CGPointMake(160, 115)]; translation2.toValue = [NSValue valueWithCGPoint:CGPointMake(160, 40)]; translation2.duration = 0.4; translation2.repeatCount = 1; translation2.autoreverses = YES; //让下面的图片上下移动 CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:@"position"]; translation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; translation.fromValue = [NSValue valueWithCGPoint:CGPointMake(160, 345)]; translation.toValue = [NSValue valueWithCGPoint:CGPointMake(160, 420)]; translation.duration = 0.4; translation.repeatCount = 1; translation.autoreverses = YES; [imgDown.layer addAnimation:translation forKey:@"translation"]; [imgUp.layer addAnimation:translation2 forKey:@"translation2"]; }
注意:在模拟器中运行时,可以通过「Hardware」-「Shake Gesture」来测试「摇一摇」功能。如下:
“扫一扫”功能的实现:
基于AVCaptureDevice做的二维码扫描器,基本步骤如下:
初始化相机,生成扫描器
设置参数
- (void)setupCamera { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil]; _output = [[AVCaptureMetadataOutput alloc]init]; [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; _session = [[AVCaptureSession alloc]init]; [_session setSessionPreset:AVCaptureSessionPresetHigh]; if ([_session canAddInput:self.input]) { [_session addInput:self.input]; } if ([_session canAddOutput:self.output]) { [_session addOutput:self.output]; } // 条码类型 AVMetadataObjectTypeQRCode _output.metadataObjectTypes = [NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode, nil]; dispatch_async(dispatch_get_main_queue(), ^{ //更新界面 _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session]; _preview.videoGravity = AVLayerVideoGravityResizeAspectFill; _preview.frame = CGRectMake(0, 0, CGRectGetWidth(self.centerView.frame), CGRectGetHeight(self.centerView.frame)); [self.centerView.layer insertSublayer:self.preview atIndex:0]; [_session startRunning]; }); }); }
在viewWillAppear和viewWillDisappear里对session做优化(timer是个扫描动画的计时器)
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (_session && ![_session isRunning]) { [_session startRunning]; } timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scanningAnimation) userInfo:nil repeats:YES]; [self setupCamera]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; _count = 0; [timer invalidate]; [self stopReading]; }
处理扫描结果
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { NSString *stringValue; if ([metadataObjects count] >0){ AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0]; stringValue = metadataObject.stringValue; NSLog(@"%@",stringValue); } [_session stopRunning]; [timer invalidate]; _count ++ ; [self stopReading]; if (stringValue && _count == 1) { //扫描完成 } }
用二维码扫描器扫描自己的二维码:
NSString *url = [NSURL URLWithString:@"html/judgement.html" relativeToURL:[ZXApiClient sharedClient].baseURL].absoluteString; if ([stringValue hasPrefix:url]) { //如果扫出来的url是自己的域名开头的,那么做如下的处理 }
最后附上自己完整的源码:
// Created by Ydw on 16/3/15. // Copyright © 2016年 IZHUO.NET. All rights reserved. // import “ViewController.h” import <AVFoundation/AVFoundation.h> @interface ViewController () { int number; NSTimer *timer; NSInteger _count; BOOL upOrdown; AVCaptureDevice *lightDevice; } @property (nonatomic,strong) UIView *centerView;//扫描的显示视图 /** * 二维码扫描参数 */ @property (strong,nonatomic) AVCaptureDevice *device; @property (strong,nonatomic) AVCaptureDeviceInput *input; @property (strong,nonatomic) AVCaptureMetadataOutput *output; @property (strong,nonatomic) AVCaptureSession *session; @property (strong,nonatomic) AVCaptureVideoPreviewLayer *preview; @property (nonatomic,retain) UIImageView *imageView;//扫描线 (void)setupCamera; (void)stopReading; @end @implementation ViewController - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (_session && ![_session isRunning]) { [_session startRunning]; } timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scanningAnimation) userInfo:nil repeats:YES]; [self setupCamera]; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor clearColor]; self.automaticallyAdjustsScrollViewInsets = NO; _count = 0 ; //初始化闪光灯设备 lightDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //扫描范围 _centerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))]; _centerView.backgroundColor = [UIColor clearColor]; [self.view addSubview:_centerView]; //扫描的视图加载 UIView *scanningViewOne = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 120)]; scanningViewOne.backgroundColor= [[UIColor blackColor] colorWithAlphaComponent:0.4]; [self.centerView addSubview:scanningViewOne]; UIView *scanningViewTwo = [[UIView alloc]initWithFrame:CGRectMake(0, 120, (self.view.frame.size.width-300)/2, 300)]; scanningViewTwo.backgroundColor= [[UIColor blackColor] colorWithAlphaComponent:0.4]; [self.centerView addSubview:scanningViewTwo]; UIView *scanningViewThree = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame)/2+150, 120, (self.view.frame.size.width-300)/2, 300)]; scanningViewThree.backgroundColor= [[UIColor blackColor] colorWithAlphaComponent:0.4]; [self.centerView addSubview:scanningViewThree]; UIView *scanningViewFour = [[UIView alloc]initWithFrame:CGRectMake(0, 420, self.view.frame.size.width,CGRectGetHeight(self.view.frame)- 420)]; scanningViewFour.backgroundColor= [[UIColor blackColor] colorWithAlphaComponent:0.4]; [self.centerView addSubview:scanningViewFour]; UILabel *labIntroudction= [[UILabel alloc] initWithFrame:CGRectMake(15, 430, self.view.frame.size.width - 30, 30)]; labIntroudction.backgroundColor = [UIColor clearColor]; labIntroudction.textAlignment = NSTextAlignmentCenter; labIntroudction.textColor = [UIColor whiteColor]; labIntroudction.text = @"请将企业邀请码放入扫描框内"; [self.centerView addSubview:labIntroudction]; UIButton *openLight = [[UIButton alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame)/2-25, 470, 50, 50)]; [openLight setImage:[UIImage imageNamed:@"灯泡"] forState:UIControlStateNormal]; [openLight setImage:[UIImage imageNamed:@"灯泡2"] forState:UIControlStateSelected]; [openLight addTarget:self action:@selector(openLightWay:) forControlEvents:UIControlEventTouchUpInside]; [self.centerView addSubview:openLight]; //扫描线 _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame)/2-110, 130, 220, 5)]; _imageView.image = [UIImage imageNamed:@"scanning@3x"]; [self.centerView addSubview:_imageView]; } - (void)viewWillDisappear:(BOOL)animated { _count= 0; [timer invalidate]; [self stopReading]; } pragma mark -- 设置参数 - (void)setupCamera { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil]; _output = [[AVCaptureMetadataOutput alloc]init]; [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; _session = [[AVCaptureSession alloc]init]; [_session setSessionPreset:AVCaptureSessionPresetHigh]; if ([_session canAddInput:self.input]) { [_session addInput:self.input]; } if ([_session canAddOutput:self.output]) { [_session addOutput:self.output]; } // 条码类型 AVMetadataObjectTypeQRCode _output.metadataObjectTypes = [NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode, nil]; dispatch_async(dispatch_get_main_queue(), ^{ //更新界面 _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session]; _preview.videoGravity = AVLayerVideoGravityResizeAspectFill; _preview.frame = CGRectMake(0, 0, CGRectGetWidth(self.centerView.frame), CGRectGetHeight(self.centerView.frame)); [self.centerView.layer insertSublayer:self.preview atIndex:0]; [_session startRunning]; }); }); } //扫描动画 - (void)scanningAnimation { if (upOrdown == NO) { number ++; _imageView.frame = CGRectMake(CGRectGetWidth(self.view.frame)/2-115, 130+2*number, 230, 5); if (2*number == 280) { upOrdown = YES; } } else { number --; _imageView.frame = CGRectMake(CGRectGetWidth(self.view.frame)/2-115, 130+2*number, 230, 5); if (number == 0) { upOrdown = NO; } } } - (void)stopReading { [_session stopRunning]; _session = nil; [_preview removeFromSuperlayer]; [timer invalidate]; timer = nil ; } -(void)openLightWay:(UIButton *)sender { if (![lightDevice hasTorch]) {//判断是否有闪光灯 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"当前设备没有闪光灯,不能提供手电筒功能" message:nil preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]; [alert addAction:sureAction]; [self presentViewController:alert animated:YES completion:nil]; return; } sender.selected = !sender.selected; if (sender.selected == YES) { [lightDevice lockForConfiguration:nil]; [lightDevice setTorchMode:AVCaptureTorchModeOn]; [lightDevice unlockForConfiguration]; } else { [lightDevice lockForConfiguration:nil]; [lightDevice setTorchMode: AVCaptureTorchModeOff]; [lightDevice unlockForConfiguration]; } } pragma mark -- AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { NSString *stringValue; if ([metadataObjects count] >0){ AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0]; stringValue = metadataObject.stringValue; NSLog(@"%@",stringValue); } [_session stopRunning]; [timer invalidate]; _count ++ ; [self stopReading]; if (stringValue && _count == 1) { //扫描完成 } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end