欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS实现“摇一摇”与“扫一扫”功能示例代码

程序员文章站 2024-02-17 20:39:40
“摇一摇”功能的实现: iphone对 “摇一摇”有很好的支持,总体说来就两步: 在视图控制器中打开接受“摇一摇”的开关; - (void)viewdi...

“摇一摇”功能的实现:

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」来测试「摇一摇」功能。如下:

iOS实现“摇一摇”与“扫一扫”功能示例代码

“扫一扫”功能的实现:

基于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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。