前言:本来要更新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;//允许编辑
第二步,通过ActionSheet来让用户选择是拍照还是到相册选择,然后模态的显示
[self presentViewController:self.imagePikerViewController animated:YES completion:NULL];
注意,要先判断相机是否可用,然后在进入相机(有可能相机坏了,或者在虚拟机上运行的)
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];
第三部,代理函数处理拍照或者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]; }
二 自定义拍照界面
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];
第三步,为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]; } }
拍照的Button
- (IBAction)takePicture:(id)sender { [self.imagePikerViewController takePicture]; }
取消的Button
- (IBAction)cancelTakePicture:(id)sender { [self dismissViewControllerAnimated:YES completion:NULL]; }
第四步 在代理中处理图片
-(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]; }
注意,如果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.
直接忽略就是了,没有任何影响,貌似是IOS 8的一个bug