iOS-オリジナルフレームを使ってスイープ機能を実現
11456 ワード
システムのフレームワークを利用してスイープ機能を実現します.
機能を実現する前の項目構成
このアイテムはカメラとアルバムに使うためです.だから、私たちはinfo.plistに訪問を許可するかどうかを問い合わせる権限を設定します.カメラを呼び出す必要がありますので、本物のマシンで運転します.
機能分析
機能の需要分析から、この機能をスキャンすると、以下のいくつかの機能点に分けられます.は、デバイスを起動するときに、loading view を設定する. CGContactextRefを使用して、第一スキャニングインターフェースUI を描画する. NSTimerを用いたスキャンラインアニメーション を実現する. AVFoundationフレームを使ってスキャン機能を実現する は、二次元コード画像をスキャンすることを実現し(システムは二次元コードだけをサポートし、バーコードはサポートしない)、システムフラッシュ を起動する.は、スキャンが完了したら前のインターフェース(Block逆方向転送値) に値を伝える.
具体的に実現するデバイスを起動するときに、loading view 1を設定します. .CGContactextRefを使用して、インターフェースUIをスキャンする1.UID Viewを引き継ぐScanViewを作成し、mファイルに次の描画コードを書き込みます. NSTimerを用いて走査線アニメーションを実現するスキャンコードは、以下の通りである. AVFoundationを使ってスキャン機能を実現する1.AVCapture Metadata Output Objects Delegateを遵守する.初期化コードは以下の通りです.
これで、生フレームを使って二次元コードをスキャンする機能が実現され、原生を使って一つの欠陥があるということは、画像のバーコードをスキャンすることができないということです.この機能を実現するためには、
機能を実現する前の項目構成
このアイテムはカメラとアルバムに使うためです.だから、私たちはinfo.plistに訪問を許可するかどうかを問い合わせる権限を設定します.カメラを呼び出す必要がありますので、本物のマシンで運転します.
機能分析
機能の需要分析から、この機能をスキャンすると、以下のいくつかの機能点に分けられます.
具体的に実現する
UIActivityIndicatorView
を引き継ぐLoadViewを作成します.mファイルに初期化コードを書きます.- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//
self.frame = CGRectMake((ScreenWidth - 100)/2, (ScreenHeight - 100)/2, 100, 100);
//
self.backgroundColor = [UIColor blackColor];
self.layer.cornerRadius = 10;
// ( 、 、 )
self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
//
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 60, 80, 40)];
label.text = @"loading...";
label.font = [UIFont systemFontOfSize:14];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
[self addSubview:label];
}
return self;
}
2.LoadViewをbgViewに追加する:- (void)setupBgView {
_bgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)];
_bgView.backgroundColor = [UIColor blackColor];
LoadView *loadView = [[LoadView alloc]init];
[_bgView addSubview:loadView];
//
[loadView startAnimating];
}
- (void)drawRect:(CGRect)rect {
CGFloat rectWidth = 50;
CGFloat rectHeight = 200;
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat black[4] = {0.0, 0.0, 0.0, _alphaValue};
CGContextSetFillColor(context, black);
//top
CGRect rect1 = CGRectMake(0, 0, self.frame.size.width, rectHeight);
CGContextFillRect(context, rect1);
//left
rect1 = CGRectMake(0, rectHeight, rectWidth, rectHeight);
CGContextFillRect(context, rect1);
//bottom
rect1 = CGRectMake(0, rectHeight * 2, self.frame.size.width, self.frame.size.height - rectHeight * 2);
CGContextFillRect(context, rect1);
//right
rect1 = CGRectMake(self.frame.size.width - rectWidth, rectHeight, rectWidth, rectHeight);
CGContextFillRect(context, rect1);
CGContextStrokePath(context);
// ( )
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 1);
CGContextAddRect(context, CGRectMake(rectWidth, rectHeight, self.frame.size.width - rectWidth * 2, rectHeight));
CGContextStrokePath(context);
CGFloat lineWidth = 10;
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
// Draw them with a 2.0 stroke width so they are a bit more visible.
CGContextSetLineWidth(context, 2.0);
//
CGContextMoveToPoint(context, rectWidth, rectHeight);
CGContextAddLineToPoint(context, rectWidth + lineWidth, rectHeight);
//
CGContextMoveToPoint(context, rectWidth, rectHeight);
CGContextAddLineToPoint(context, rectWidth, rectHeight + lineWidth);
//
CGContextMoveToPoint(context, rectWidth, rectHeight * 2);
CGContextAddLineToPoint(context, rectWidth + lineWidth, rectHeight * 2);
//
CGContextMoveToPoint(context, rectWidth, rectHeight * 2 - lineWidth);
CGContextAddLineToPoint(context, rectWidth, rectHeight * 2);
//
CGContextMoveToPoint(context, self.frame.size.width - rectWidth - lineWidth, rectHeight);
CGContextAddLineToPoint(context, self.frame.size.width - rectWidth, rectHeight);
//
CGContextMoveToPoint(context, self.frame.size.width - rectWidth, rectHeight);
CGContextAddLineToPoint(context, self.frame.size.width - rectWidth, rectHeight + lineWidth);
//
CGContextMoveToPoint(context, self.frame.size.width - rectWidth - lineWidth, rectHeight * 2);
CGContextAddLineToPoint(context, self.frame.size.width - rectWidth, rectHeight * 2);
//
CGContextMoveToPoint(context, self.frame.size.width - rectWidth, rectHeight * 2 - lineWidth);
CGContextAddLineToPoint(context, self.frame.size.width - rectWidth, rectHeight * 2);
CGContextStrokePath(context);
}
2.scanViewをself.viewに追加する:- (void)setupScanView {
_scan = [[ScanView alloc]initWithFrame:self.view.bounds];
_scan.backgroundColor = [UIColor clearColor];
_slideLineView = [[UIView alloc]initWithFrame:CGRectMake(_viewWidth, 201, ScreenWidth - _viewWidth * 2, 1)];
_slideLineView.backgroundColor = [UIColor greenColor];
[_scan addSubview:_slideLineView];
[self.view addSubview:_scan];
[self setupSubView];
}
3.self.viewのフラッシュボタンとアルバム訪問ボタンを設定する:- (void)setupSubView {
_titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 500, ScreenWidth, 50.0)];
_titleLabel.text = @" ";
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.textColor = [UIColor whiteColor];
[_scan addSubview:_titleLabel];
_lightButton = [[UIButton alloc]initWithFrame:CGRectMake(100, 580, 50, 50)];
[_lightButton setTitle:@"light" forState:UIControlStateNormal];
[_lightButton addTarget:self action:@selector(lightButtonDidTouch) forControlEvents:UIControlEventTouchUpInside];
[_scan addSubview:_lightButton];
_imageButton = [[UIButton alloc]initWithFrame:CGRectMake(200, 580, 50, 50)];
[_imageButton setTitle:@" " forState:UIControlStateNormal];
[_imageButton addTarget:self action:@selector(imageButtonDidTouch) forControlEvents:UIControlEventTouchUpInside];
[_scan addSubview:_imageButton];
}
4.フラッシュボタンのクリックイベント:AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (![device hasTorch]) {
NSLog(@"no torch");
}else {
[device lockForConfiguration:nil];
if (!self.isOpen) {
[device setTorchMode: AVCaptureTorchModeOn];
self.isOpen = YES;
}
else {
[device setTorchMode: AVCaptureTorchModeOff];
self.isOpen = NO;
}
[device unlockForConfiguration];
}
5.アルバムボタンにアクセスするクリックイベント:- (void)imageButtonDidTouch {
[_timer invalidate];
_timer = nil;
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
// ( )
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
//
picker.delegate = self;
//
picker.allowsEditing = YES;
//
[self presentViewController:picker animated:YES completion:nil];
}
#pragma mark UIImagePickerControllerDelegate methods
//
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
//
[picker dismissViewControllerAnimated:YES completion:nil];
// URL CIImage
CIImage *ciImage = [[CIImage alloc]initWithCGImage:image.CGImage];
if (ciImage){
// CIDetector
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy: CIDetectorAccuracyHigh }];
NSArray *features = [detector featuresInImage:ciImage];
if ([features count] > 0) {
for (CIFeature *feature in features) {
if (![feature isKindOfClass:[CIQRCodeFeature class]]) {
continue;
}
CIQRCodeFeature *qrFeature = (CIQRCodeFeature *)feature;
NSString *code = qrFeature.messageString;
if (self.resultBlock) {
self.resultBlock(code);
[self scanSuccess];
}
//
[self.navigationController popViewControllerAnimated:YES];
}
}else {
[self setupTimer];
}
}
}
//
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)setupTimer {
_timer = [NSTimer scheduledTimerWithTimeInterval:1.8 target:self selector:@selector(animationView) userInfo:nil repeats:YES];
[_timer fire];
}
- (void)animationView {
[UIView animateWithDuration:1.5 animations:^{
_slideLineView.transform = CGAffineTransformMakeTranslation(0, 200);
} completion:^(BOOL finished) {
_slideLineView.transform = CGAffineTransformIdentity;
}];
}
- (void)setupAVFoundation {
//
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
//
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//
_session = [[AVCaptureSession alloc]init];
//
[_session setSessionPreset:AVCaptureSessionPresetHigh];
[_session addInput:input];
[_session addOutput:output];
// ( )
output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
_previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
_previewLayer.frame = self.view.layer.bounds;
[self.view.layer insertSublayer:_previewLayer atIndex:0];
//
[_session startRunning];
// loading view
[_bgView removeFromSuperview];
}
2.AVCapture Metadata Output Object Delegateを実現する.#pragma mark
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
if (metadataObjects.count > 0) {
[_timer invalidate];
_timer = nil;
[_session stopRunning];
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex: 0];
if (self.resultBlock) {
self.resultBlock(metadataObject.stringValue);
[self scanSuccess];
}
//
[self.navigationController popViewControllerAnimated:YES];
}
}
//
- (void)scanSuccess {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
AudioServicesPlaySystemSound(1109);
}
結尾語これで、生フレームを使って二次元コードをスキャンする機能が実現され、原生を使って一つの欠陥があるということは、画像のバーコードをスキャンすることができないということです.この機能を実現するためには、
ZXingObjC
フレームを使用することができる.プロジェクトの住所、10番目