Snip20170312_4.png
使用系統(tǒng)提供的UIImagePickerController可以實現(xiàn)基本的拍照和錄制視頻的功能秧荆,但是很多時候從UI那邊拿到的設計圖都是和系統(tǒng)的不一樣的祠墅,我們需要自定義相機的界面。
大概思路
1.根據(jù)UI的設計圖响谓,把基本的界面先搭建出來(感覺是廢話⊙o⊙)损合。
2.使用AVFoundation必須的幾個東西 -device,input娘纷,output塌忽,session,connection失驶,previewLayer
3.按鈕點擊之后的邏輯處理 - 閃光燈土居,前后攝像頭的切換等
主要的內容就是AVFoundation的使用
//1.獲取device(audio,video)
//2.根據(jù)device創(chuàng)建input
//3.創(chuàng)建輸出output(下面圖片是輸出的方式,共7種)
//4.創(chuàng)建全局的會話session擦耀,并且把輸入和輸出都添加到session中棉圈,統(tǒng)一管理
//5.如果需要實時的顯示,就用AVCaptureVideoPreviewLayer預覽圖層來顯示
圖片還是視頻區(qū)別在于輸出output的不同
14881125871512.jpg
直接上代碼
//
#import "CustomCameraVC.h"
#import "UIControl+BlocksKit.h"
#import "UIView+YGYAdd.h"
#import <AVFoundation/AVFoundation.h>
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
@interface CustomCameraVC () <AVCapturePhotoCaptureDelegate>
//UI界面搭建
@property (nonatomic, strong) UIView *topView;
@property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UIButton *flashModeButton;
@property (nonatomic, strong) UIButton *cameraButton;
@property (nonatomic, strong) UIView *middleView;
@property (nonatomic, strong) UIView *bottomView;
@property (nonatomic, strong) UIButton *albumButton;
@property (nonatomic, strong) UIButton *takePhotoButton;
@property (nonatomic, strong) UIButton *musicButton;
//自定義相機(AVFoundation)
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureDevice *device;
@property (nonatomic, strong) AVCaptureDeviceInput *input;
@property (nonatomic, strong) AVCaptureStillImageOutput *output;
@property (nonatomic, strong) AVCaptureConnection *connection;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preViewLayer;
@property (nonatomic, strong) NSArray *flashModelArray;
@property (nonatomic, assign) NSInteger flashModel;
@end
@implementation CustomCameraVC
- (void)viewDidLoad {
[super viewDidLoad];
_flashModelArray = @[@"icon-pz-sgd-gb",@"icon-pz-sgd-zd",@"icon-pz-sgd"];
_flashModel = 0;
[self setupUI];
[self customCamera];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[_session startRunning];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[_session stopRunning];
}
- (void)setupUI {
//頂部UI
[self makeTopUI];
//中間預覽圖層
[self makeMiddleUI];
//底部UI
[self makeBottomUI];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
//---top
_topView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight*0.2);
_closeButton.frame = CGRectMake(0, 0, 50, 50);
_closeButton.centerY = _topView.centerY;
_flashModeButton.frame = CGRectMake(0, 0, 50, 50);
_flashModeButton.center = _topView.center;
_cameraButton.frame = CGRectMake(0, 0, 50, 50);
_cameraButton.centerY = _topView.centerY;
_cameraButton.right = _topView.right;
//---middle
_middleView.frame = CGRectMake(0, CGRectGetMaxY(_topView.frame), kScreenWidth, kScreenHeight*0.6);
_preViewLayer.frame = _middleView.bounds;
//---bottom
_bottomView.frame = CGRectMake(0, CGRectGetMaxY(_middleView.frame), kScreenWidth, kScreenHeight*0.2);
_albumButton.frame = CGRectMake(0, 0, 50, 50);
// _albumButton.centerY = _bottomView.centerY;//不能這么寫眷蜓,超出父控件
_albumButton.centerY = _bottomView.height*0.5;
_takePhotoButton.frame = CGRectMake(0, 0, 50, 50);
// _takePhotoButton.center = _bottomView.center;
_takePhotoButton.center = CGPointMake(_bottomView.width*0.5, _bottomView.height*0.5);
_musicButton.frame = CGRectMake(0, 0, 50, 50);
// _musicButton.centerY = _bottomView.centerY;
_musicButton.centerY = _bottomView.height*0.5;
_musicButton.right = _bottomView.right;
}
- (void)makeTopUI {
_topView = [[UIView alloc] init];
_topView.backgroundColor = [UIColor grayColor];
_closeButton = [[UIButton alloc] init];
[_closeButton setImage:[UIImage imageNamed:@"icon-pz-exit"] forState:UIControlStateNormal];
[_closeButton bk_addEventHandler:^(id _Nonnull sender) {
//關閉控制器
[self dismissViewControllerAnimated:YES completion:nil];
} forControlEvents:UIControlEventTouchUpInside];
_flashModeButton = [[UIButton alloc] init];
[_flashModeButton setImage:[UIImage imageNamed:@"icon-pz-sgd"] forState:UIControlStateNormal];
[_flashModeButton bk_addEventHandler:^(id _Nonnull sender) {
//切換閃光燈的模式
// icon-pz-sgd-zd
[self changeFlashModel];
} forControlEvents:UIControlEventTouchUpInside];
_cameraButton = [[UIButton alloc] init];
[_cameraButton setImage:[UIImage imageNamed:@"icon-pz-fz"] forState:UIControlStateNormal];
[_cameraButton bk_addEventHandler:^(id _Nonnull sender) {
//切換前后攝像頭
[self changeCamera];
} forControlEvents:UIControlEventTouchUpInside];
[_topView addSubview:_closeButton];
[_topView addSubview:_flashModeButton];
[_topView addSubview:_cameraButton];
[self.view addSubview:_topView];
}
- (void)makeMiddleUI {
_middleView = [[UIView alloc] init];
[self.view addSubview:_middleView];
}
- (void)makeBottomUI {
_bottomView = [[UIView alloc] init];
_bottomView.backgroundColor = [UIColor grayColor];
[self.view addSubview:_bottomView];
_albumButton = [[UIButton alloc] init];
[_albumButton setImage:[UIImage imageNamed:@"icon-pz-TP"] forState:UIControlStateNormal];
[_albumButton bk_addEventHandler:^(id _Nonnull sender) {
//從相冊選取
} forControlEvents:UIControlEventTouchUpInside];
_takePhotoButton = [[UIButton alloc] init];
[_takePhotoButton setImage:[UIImage imageNamed:@"icon-pz-pz"] forState:UIControlStateNormal];
[_takePhotoButton bk_addEventHandler:^(id _Nonnull sender) {
[self takePhoto];
} forControlEvents:UIControlEventTouchUpInside];
_musicButton = [[UIButton alloc] init];
[_musicButton setImage:[UIImage imageNamed:@"icon-pz-music"] forState:UIControlStateNormal];
[_musicButton bk_addEventHandler:^(id _Nonnull sender) {
//音頻選擇
} forControlEvents:UIControlEventTouchUpInside];
[_bottomView addSubview:_albumButton];
[_bottomView addSubview:_takePhotoButton];
[_bottomView addSubview:_musicButton];
}
- (void)customCamera {
_session = [[AVCaptureSession alloc] init];
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
_input = [[AVCaptureDeviceInput alloc] initWithDevice:_device error:&error];
if (error) {
NSLog(@"創(chuàng)建輸入設備失敗 -- %@",error);
return;
}
AVCaptureStillImageOutput *output = [[AVCaptureStillImageOutput alloc] init];
_output = output;
// _connection = [output connectionWithMediaType:AVMediaTypeVideo];//千萬不要在這里獲取分瘾,輸入和輸出都沒有加入session,所以獲取的connection始終是nil
if ([_session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
[_session setSessionPreset:AVCaptureSessionPreset1280x720];
}
if ([_session canAddInput:_input]) {
[_session addInput:_input];
}else {
NSLog(@"添加輸入設備失敗");
return;
}
if ([_session canAddOutput:output]) {
[_session addOutput:output];
}else {
NSLog(@"添加輸出設備失敗");
return;
}
AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
layer.videoGravity = AVLayerVideoGravityResizeAspectFill ;
_preViewLayer = layer;
[_middleView.layer addSublayer:layer];
}
- (void)takePhoto {//拍照就是從輸出(output)從connection中獲取一張圖片
_connection = [_output connectionWithMediaType:AVMediaTypeVideo];
[_output captureStillImageAsynchronouslyFromConnection:_connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer) {
NSData *data = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:data];
//顯示還是存儲到相冊的邏輯
NSLog(@"%@",image);
}
}];
}
- (void)changeCamera {//切換攝像頭 - input改變
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (int i = 0; i < devices.count; ++i) {
AVCaptureDevice *device = devices[i];
if (_device.position != device.position) {
_device = device;
break;//找到就不要再找吁系,邏輯就不對了
}
}
NSError *error = nil;
AVCaptureDeviceInput *newInput = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
if (error) {
NSLog(@"創(chuàng)建輸入設備失敗 -- %@",error);
return;
}
[_session beginConfiguration];
[_session removeInput:_input];
if ([_session canAddInput:newInput]) {
[_session addInput:newInput];
_input = newInput;
}
[_session commitConfiguration];
}
- (void)changeFlashModel {
//FlashModel是輸入設備的屬性,不需要使用session
if ([_device hasFlash]) {//必須判斷德召,否則前置攝像頭的時候就會奔潰
[_device lockForConfiguration:nil];
[_device setFlashMode:_flashModel++ % 3];//注意:閃關燈不是手電筒,只有拍的時候才會亮
[_device unlockForConfiguration];
[_flashModeButton setImage:[UIImage imageNamed:_flashModelArray[_flashModel % 3]] forState:UIControlStateNormal];
}
}