iOS - AVFoundation - 自定义相机界面

iOS - AVFoundation - 自定义相机界面_第1张图片
Snip20170312_4.png

使用系统提供的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的不同

iOS - AVFoundation - 自定义相机界面_第2张图片
14881125871512.jpg

直接上代码

//

#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];
    }
    
}

你可能感兴趣的:(iOS - AVFoundation - 自定义相机界面)