iOS之实现“摇一摇”与“扫一扫”功能

举报
Serendipity·y 发表于 2022/02/16 23:19:59 2022/02/16
【摘要】 "摇一摇"功能的实现: iPhone对 "摇一摇"有很好的支持,总体说来就两步: 在视图控制器中打开接受“摇一摇”的开关; - (void)viewDidLoad { // 设置允许摇一摇...

"摇一摇"功能的实现:

iPhone对 "摇一摇"有很好的支持,总体说来就两步:

  • 在视图控制器中打开接受“摇一摇”的开关;
 - (void)viewDidLoad {
    // 设置允许摇一摇功能
    [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
    // 并让自己成为第一响应者
    [self becomeFirstResponder];
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 在“摇一摇”触发的制定的方法中实现需要实现的功能(”摇一摇“检测方法)。
pragma mark - “摇一摇”相关方法
// 摇一摇开始摇动  
- (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;  
}  

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

”摇一摇“的动画效果:

pragma mark - “摇一摇”动画效果
- (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"];    
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

注意:在模拟器中运行时,可以通过「Hardware」-「Shake Gesture」来测试「摇一摇」功能。如下:

这里写图片描述

“扫一扫”功能的实现:

基于AVCaptureDevice做的二维码扫描器,基本步骤如下:

  • 初始化相机,生成扫描器
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];
        });
    });
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 在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];
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 处理扫描结果
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) {
        //扫描完成
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 用二维码扫描器扫描自己的二维码:
NSString *url = [NSURL URLWithString:@"html/judgement.html" relativeToURL:[ZXApiClient sharedClient].baseURL].absoluteString;

    if ([stringValue hasPrefix:url]) {
        //如果扫出来的url是自己的域名开头的,那么做如下的处理
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 最后附上自己完整的源码:
// 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


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213

文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/50890903

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。