使用系统提供的UIImagePickerController可以实现基本的拍照和录制视频的功能,但是很多时候从UI那边拿到的设计图都是和系统的不一样的,我们需要自定义相机的界面。
大概思路
1.根据UI的设计图,把基本的界面先搭建出来(感觉是废话⊙o⊙)。
2.使用AVFoundation必须的几个东西 -device,input,output,session,connection,previewLayer
3.按钮点击之后的逻辑处理 - 闪光灯,前后摄像头的切换等
主要的内容就是AVFoundation的使用
//1.获取device(audio,video)
//2.根据device创建input
//3.创建输出output(下面图片是输出的方式,共7种)
//4.创建全局的会话session,并且把输入和输出都添加到session中,统一管理
//5.如果需要实时的显示,就用AVCaptureVideoPreviewLayer预览图层来显示
图片还是视频区别在于输出output的不同
直接上代码
//
#import "CustomCameraVC.h"
#import "UIControl+BlocksKit.h"
#import "UIView+YGYAdd.h"
#import
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
@interface CustomCameraVC ()
//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(@"创建输入设备失败 -- %@",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(@"创建输入设备失败 -- %@",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];
}
}