转载 自定义拍照界面

原创blog,转载请注明出处 
blog.csdn.net/hello_hwc


http://blog.csdn.net/hello_hwc/article/details/44805329

前言: 
本来要更新NSURLSession的UploadTask的,结果写那个Demo的时候想要写成拍照上传,然后就想到先写一个关于拍照的Demo吧。本文会先介绍下如何使用系统提供的界面拍照和选择相册,然后自定义拍照界面。注意,本文使用的是UIImagePickerController,所以不能完全的自定义,如果想要彻底的自定义拍照,建议选择AV Foundation这个框架来做


Demo效果 
进入系统的拍照界面 


进入自定义拍照界面 


自定义前置摄像头和后置摄像头切换动画-翻页 


一 使用系统提供的界面拍照和相册选择

第一步 
保存一个UIImagePickerController的实例,然后适当的时候初始化始化。Demo选择在viewDidLoad初始化。让当前类实现UIImagePickerControllerDelegate,UINavigationControllerDelegate两个代理

@property (strong,nonatomic)UIImagePickerController * imagePikerViewController;
//初始化
self.imagePikerViewController = [[UIImagePickerController alloc] init];
self.imagePikerViewController.delegate = self;//通过代理来传递拍照的图片
self.imagePikerViewController.allowsEditing = YES;//允许编辑
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

第二步,通过ActionSheet来让用户选择是拍照还是到相册选择,然后模态的显示

[self presentViewController:self.imagePikerViewController animated:YES completion:NULL];
  • 1
  • 1

注意,要先判断相机是否可用,然后在进入相机(有可能相机坏了,或者在虚拟机上运行的)

UIAlertController * alertController = [UIAlertController alertControllerWithTitle: nil
                                                                              message: nil
                                                                       preferredStyle:UIAlertControllerStyleActionSheet];

    [alertController addAction: [UIAlertAction actionWithTitle: @"Take Photo" style: UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
            self.imagePikerViewController.sourceType = UIImagePickerControllerSourceTypeCamera;
            [self presentViewController:self.imagePikerViewController animated:YES completion:NULL];
        }else{
            [self showAlertWithMessage:@"Camera is not available in this device or simulator"];
        }
    }]];
    [alertController addAction: [UIAlertAction actionWithTitle: @"Choose Existing Photo" style: UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
            self.imagePikerViewController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            [self presentViewController:self.imagePikerViewController animated:YES completion:NULL];
        }
    }]];
    [alertController addAction: [UIAlertAction actionWithTitle: @"Cancel" style: UIAlertActionStyleCancel handler:nil]];
    [self presentViewController: alertController animated: YES completion: nil];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

第三部,代理函数处理拍照或者cancel事件

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    UIImage * image = info[UIImagePickerControllerEditedImage];
    if (!image) {
        image = info[UIImagePickerControllerOriginalImage];
    }
    self.imageview.image = image;
    [self dismissViewControllerAnimated:YES completion:NULL];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    [self dismissViewControllerAnimated:YES completion:NULL];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

二 自定义拍照界面

UIImagePickerController的自定义界面比较简单,通过设置cameraOverlayView这个属性为自定义的View就能自定义。 
第一步 创建一个View 
创建xib文件 

拖拽控件,进行autoLayout,最终效果如图 
 
把fileOwner设置成CustomTakePhotoViewController 

第二步 在显示拍照界面之前,把UI设置成自己想要的,注意,把属性 
showsCameraControls设置为NO,不让默认的界面出现。


self.imagePikerViewController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePikerViewController.showsCameraControls = NO;
[[NSBundle mainBundle] loadNibNamed:@"CustomOverLayview" owner:self options:nil];
self.takePictureButton.layer.cornerRadius = 20;
self.takePictureButton.clipsToBounds = YES;
self.overlayView.frame = self.imagePikerViewController.cameraOverlayView.frame;
self.overlayView.backgroundColor = [UIColor clearColor];
self.imagePikerViewController.cameraOverlayView = self.overlayView;
self.overlayView = nil;
[self presentViewController:self.imagePikerViewController animated:YES completion:NULL];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

第三步,为view上的控件添加动作 
Segment Control负责切换前置摄像头和后置摄像头,为了流畅,在切换的时候显示动画。

- (IBAction)cameraSelect:(UISegmentedControl *)sender{
    NSInteger index = sender.selectedSegmentIndex;

    if (index == 0) {
        [UIView transitionWithView:self.imagePikerViewController.view duration:1.0 options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionTransitionCurlDown animations:^{
            self.imagePikerViewController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
        } completion:NULL];
    }else{
        [UIView transitionWithView:self.imagePikerViewController.view duration:1.0 options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionTransitionCurlUp animations:^{
            [self.imagePikerViewController setCameraDevice:UIImagePickerControllerCameraDeviceRear];
        } completion:NULL];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

拍照的Button

- (IBAction)takePicture:(id)sender {
    [self.imagePikerViewController takePicture];
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

取消的Button

- (IBAction)cancelTakePicture:(id)sender {
    [self dismissViewControllerAnimated:YES completion:NULL];
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

第四步 在代理中处理图片

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    UIImage * image = info[UIImagePickerControllerEditedImage];
    if (!image) {
        image = info[UIImagePickerControllerOriginalImage];
    }
    self.imageview.image = image;
    [self dismissViewControllerAnimated:YES completion:NULL];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注意,如果log输出

Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
  • 1
  • 1

直接忽略就是了,没有任何影响,貌似是iOS 8的一个bug

原文地址:https://www.cnblogs.com/yecong/p/6184036.html