iOS项目实战之自定义相机
一、基本思路1、创建一个导航控制器,承载两个控制器:拍照、照片预览;
2、分别创建这两个控制器,由于视图均为静态视图,所以直接用xib创建即可;
3、引用AVFoundation框架,通过媒体与数据流的交互来获取图片;
4、各种封装
二、使用到的几个类及相关说明:
SAImagePickerController:继承导航控制器类,用他来创建一个自定义相机SACameraCtrl:拍照控制器,即拍照主界面,取景,摄像头切换、闪光灯开关、拍照按钮都在这个界面上展示;SAPhotoViewCtrl:照片预览控制器,即拍照后的预览界面,查看照片效果、确定使用照片或重拍;SAPreview:自定义View,拍照取景的那个视图,自定义是为了能够监听处理该视图上的事件,如对焦等。
三、基本界面预览:
四、关键代码:1、SACameraCtrl.h//
//SACameraCtrl.h
//Test
//
//Created by 余西安 on 15/4/13.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SACameraCtrl : UIViewController
@end
2、SACameraCtrl.m//
//SACameraCtrl.m
//Test
//
//Created by 余西安 on 15/4/13.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import "SACameraCtrl.h"
#import "SAPreview.h"
#import "SAPhotoViewCtrl.h"
#import <AVFoundation/AVFoundation.h>
#import <CoreMotion/CoreMotion.h>
#define SourcePath [ pathForResource:@"SAImagePickerController.bundle" ofType:nil]
@interface SACameraCtrl () <UIAccelerometerDelegate>
// 输入流预览图层
@property (nonatomic, strong) AVCaptureVideoPreviewLayer*previewLayer;
@property (weak, nonatomic) IBOutlet SAPreview *preview;
// AVCaptureSession对象来执行输入设备和输出设备之间的数据传递
@property (nonatomic, strong) AVCaptureSession *session;
// 设备输入流
@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;
// 照片输出流
@property (nonatomic, strong) AVCaptureStillImageOutput *imageOutput;
// 图片输出视图
@property (nonatomic, strong) UIImageView *cameraShowView;
// 摄像头数组
@property (nonatomic, strong, readonly) NSArray *devices; // AVCaptureDevices
// 闪光灯切换按钮
@property (weak, nonatomic) IBOutlet UIButton *flashButton;
@end
@implementation SACameraCtrl
- (void)viewDidLoad
{
;
// 创建交互流
self.session = [ init];
self.session.sessionPreset = AVCaptureSessionPresetPhoto;
// 媒体输入
AVCaptureDevice *device = ;
;
self.deviceInput = ;
if();
// 媒体输出
self.imageOutput = [ init];
self.imageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG};
AVCaptureConnection * connection = ;
connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
if();
// 媒体预览
self.previewLayer = ;
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.previewLayer.position = self.preview.center;
;
[ beginGeneratingDeviceOrientationNotifications];
;
}
#pragma mark - 前后摄像头
- (NSArray *)devices
{
return ;
}
- (void)viewWillAppear:(BOOL)animated
{
;
self.previewLayer.frame = self.preview.layer.bounds;
self.navigationController.navigationBar.hidden = YES;
;
}
- (void)viewDidAppear:(BOOL)animated
{
;
[ setStatusBarHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
;
[ setStatusBarHidden:NO];
}
- (void)viewDidDisappear:(BOOL)animated
{
;
;
}
/// 媒体预览图层手势事件
- (void)setPreviewGesture
{
// 注册一个手势事件来实现对焦功能
UITapGestureRecognizer *tap = [ initWithTarget:self action:@selector(tapPreview:)];
;
}
/// 预览图层点击事件
- (void)tapPreview:(UITapGestureRecognizer *)gesture
{
CGPoint point = ;
CGPoint p = ;
;
self.preview.aperture.center = point;
;
}
/// 对焦事件
- (void)focusAtPoint:(CGPoint)point
{
AVCaptureDevice *device = self.deviceInput.device;
NSError *error;
if ( && )
{
if () {
;
;
;
} else {
SALog(@"Error: %@", error);
}
}
}
/// 摄像头切换事件
- (IBAction)switchCamera:(UIButton *)sender
{
if (self.devices.count < 2) return;
NSInteger oldIndex = ;
NSInteger newIndex = (oldIndex + 1) % self.devices.count;
AVCaptureDevice *newDevice = ;
AVCaptureDeviceInput *newInput = ;
if (newInput) {
;
;
;
;
self.deviceInput = newInput;
self.flashButton.hidden = !newDevice.isFlashAvailable;
}
}
/// 取消事件
- (IBAction)cancel:(UIButton *)sender
{
;
}
/// 拍照事件
- (IBAction)shutter:(UIButton *)sender
{
sender.userInteractionEnabled = NO;
AVCaptureConnection * connection = ;
connection.videoOrientation = AVCaptureVideoOrientationPortrait;
connection.videoScaleAndCropFactor = 1.0; // 获取流比例
if (!connection) {
NSLog(@"take photo failed!");
return;
}
[self.imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer == NULL) {
return;
}
NSData * imageData = ;
UIImage * image = ;
SAPhotoViewCtrl *photoView = [ initWithImage:image];
;
sender.userInteractionEnabled = YES;
}];
}
/// 闪光灯开关按钮
- (IBAction)overTurn:(UIButton *)sender
{
sender.tag = (sender.tag + 1) % 3;
NSString *imageName = ;
forState:UIControlStateNormal];
;
}
/// 切换闪光灯模式
- (void)setDevice:(AVCaptureDevice *)device FlashMode:(AVCaptureFlashMode)flashModel
{
if (device.isFlashAvailable == NO) return;
if () {
device.flashMode = flashModel;
}
;
}
@end
3、SAImagePickerController.h//
//SAImagePickerController.h
//Test
//
//Created by 余西安 on 15/4/15.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void (^SAImagePickerComplete)(UIImage *image);
@interface SAImagePickerController : UINavigationController
@property (nonatomic, copy) SAImagePickerComplete completeBlock;
+ (instancetype)pickerComplete:(SAImagePickerComplete)complete;
@end
4、SAImagePickerController.m//
//SAImagePickerController.m
//Test
//
//Created by 余西安 on 15/4/15.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import "SAImagePickerController.h"
#import "SACameraCtrl.h"
@interface SAImagePickerController ()
@end
@implementation SAImagePickerController
+ (instancetype)pickerComplete:(SAImagePickerComplete)complete
{
return [ initWithBlock:complete];
}
- (instancetype)initWithBlock:(SAImagePickerComplete)block
{
if (self = ){
if (block) self.completeBlock = block;
}
return self;
}
- (instancetype)init
{
SACameraCtrl *cameraCtrl = [ init];
if (self = ){
}
return self;
}
- (void)viewDidLoad
{
;
}
- (void)dealloc
{
SALog(@"SAImagePickerController is dealloc");
}
@end
5、SAPhotoViewCtrl.h//
//SAPhotoViewCtrl.h
//Test
//
//Created by 余西安 on 15/4/14.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAPhotoViewCtrl : UIViewController
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (instancetype)initWithImage:(UIImage *)image;
@end
6、SAPhotoViewCtrl.m//
//SAPhotoViewCtrl.m
//Test
//
//Created by 余西安 on 15/4/14.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import "SAPhotoViewCtrl.h"
#import "SAImagePickerController.h"
@interface SAPhotoViewCtrl ()
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, assign) NSInteger rotate;
@end
@implementation SAPhotoViewCtrl
- (instancetype)initWithImage:(UIImage *)image
{
if (self = ){
self.image = image;
self.rotate = 0;
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
;
self.imageView.image = self.image;
[ setStatusBarHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
;
[ setStatusBarHidden:NO];
}
- (void)viewDidLoad
{
;
}
/// 旋转图片
- (IBAction)transForm:(UIButton *)sender
{
self.rotate ++;
[UIView animateWithDuration:0.3 animations:^{
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, - M_PI_2);
}];
}
/// 重新拍摄
- (IBAction)reShutter:(UIButton *)sender
{
;
}
/// 使用照片
- (IBAction)submitImage:(UIButton *)sender
{
UIImageOrientation orientation = UIImageOrientationUp;
switch (self.rotate % 4) {
case 0:{
orientation = UIImageOrientationRight;
}break;
case 1:{
orientation = UIImageOrientationUp;
}break;
case 2:{
orientation = UIImageOrientationLeft;
}break;
case 3:{
orientation = UIImageOrientationDown;
}break;
default:break;
}
CGFloat scale = .scale;
UIImage *image = [ initWithCGImage:self.image.CGImage scale:scale orientation:orientation];
SAImagePickerController *pickerCtrl = (SAImagePickerController *)self.navigationController;
pickerCtrl.completeBlock(image);
[self dismissViewControllerAnimated:YES completion:^{
;
}];
}
@end
7、SAPreview.h//
//SAPreview.h
//Test
//
//Created by 余西安 on 15/4/14.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAPreview : UIView
@property (nonatomic, strong) UIImageView *aperture;
- (void)showAperture;
@end
8、SAPreview.m//
//SAPreview.m
//Test
//
//Created by 余西安 on 15/4/14.
//Copyright (c) 2015年 Sian. All rights reserved.
//
#import "SAPreview.h"
@implementation SAPreview
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = ){
UIImage *image = ;
self.aperture = [ initWithImage:image];
}
return self;
}
- (void)showAperture
{
;
self.aperture.transform = CGAffineTransformMakeScale(2.0, 2.0);
[UIView animateWithDuration:0.3 animations:^{
self.aperture.transform = CGAffineTransformIdentity;
}];
;
}
@end
五、基本使用一行代码搞定! SAImagePickerController *imagePicker = [SAImagePickerControllerpickerComplete:^(UIImage *image) {
self.imageView.image = image;
}];
;
六、Demo下载**** Hidden Message *****
写得非常好 请问一下 , 你所使用的字体是什么名字呢 ? 喵了个咪 发表于 2015-4-23 14:36
请问一下 , 你所使用的字体是什么名字呢 ?
按钮字体吗?系统自带默认字体,没有修改。 Sian 发表于 2015-4-24 09:35
按钮字体吗?系统自带默认字体,没有修改。
不是按钮字体 , 是代码字体 , 就是帖子里黑色背景下的代码字体 , 请问用的是哪个字体呢 ? 喵了个咪 发表于 2015-4-24 09:45
不是按钮字体 , 是代码字体 , 就是帖子里黑色背景下的代码字体 , 请问用的是哪个字体呢 ?
在功能区插入表情旁边有个插入代码,选择Objective-C语言,系统会自动布局。 Sian 发表于 2015-4-24 09:54
在功能区插入表情旁边有个插入代码,选择Objective-C语言,系统会自动布局。
那请问系统用的是哪一种字体呢 ? 我想在Xcode里也用这种字体 , 因为这种字体看着挺舒服的 . 本帖最后由 Sian 于 2015-4-24 13:15 编辑
喵了个咪 发表于 2015-4-24 10:06
那请问系统用的是哪一种字体呢 ? 我想在Xcode里也用这种字体 , 因为这种字体看着挺舒服的 .
Courier New
Consolas Sian 发表于 2015-4-24 13:04
Courier New
非常感谢 !! {:3_48:} 喵了个咪 发表于 2015-4-24 13:13
非常感谢 !!
Consolas
页:
[1]
2