2016.07.08 15:04* 字数 1837 阅读 6066评论 6喜欢 26赞赏 1

问题

在项目中,选择照片或拍照的功能很长见,由于我之前采用系统自带的UIimagePickViewController遇到一点问题:

  • 使用拍照功能,进行截取时(allowEditing = YES)时,拍照完成的图片无法拖动,没有办法进行选择性的截取图片
  • 如果使用选择相册功能,进入裁剪界面,图片是可以拖动的,唯独拍照之后进入裁剪界面无法拖动
  • 微信头像更换拍照好像也无法拖动,初步推测可能使用的系统自带的裁剪界面
  • 所以想来仔细研究一下UIImagePickViewController的属性和使用方法

UIImagePickViewController

UIImagePickerController是iOS系统提供的和系统的相册和相机交互的一个类,可以用来获取相册的照片,也可以调用系统的相机拍摄照片或者视频。该类的继承结构是:

UIImagePickerController-->UINavigationController-->UIViewController-->UIResponder-->NSObject

官方文档中对于该类的说明是:

该类只支持竖屏模式,为了保证该类被原样使用,它不支持子类,并且它的视图层次是私有的不能被修改,只支持自定义cameraOverlayView属性来展示更多信息以及和用户的交互。

由于该类继承自UINavgationController,所以在使用过程中一般实现UIImagePickerControllerDelegate和UINavigationControllerDelegate这两个代理,可以利用navgation的push 和pop操作自定义界面实现更复杂的交互效果。

下面具体分析该类的一些方法和属性.

UIImagePickViewController之常用属性

@property (nullable, nonatomic, weak) id <UINavigationControllerDelegate, UIImagePickerControllerDelegate> delegate;

该对象的代理需要实现UINavigationControllerDelegate和UIImagePickerControllerDelegate协议,nullable是xcode6.3之后引入的nullability annotations特性,主要用于在OC和swift之间的转换。这一特性主要包含两个新的类型注释nullable和nonnull,用于表示对象是否可以是NULL或nil

@property (nonatomic) UIImagePickerControllerSourceType sourceType; // default value is UIImagePickerControllerSourceTypePhotoLibrary.

sourceType用于指定要访问的系统的媒体类型。UIImagePickerControllerSourceType支持以下3种枚举类型,默认值是图片库

typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) { UIImagePickerControllerSourceTypePhotoLibrary,//照片库模式。图像选取控制器以该模式显示时会浏览系统照片库的根目录。 UIImagePickerControllerSourceTypeCamera, //相机模式,图像选取控制器以该模式显示时可以进行拍照或摄像。 UIImagePickerControllerSourceTypeSavedPhotosAlbum //相机胶卷模式,图像选取控制器以该模式显示时会浏览相机胶卷目录。};

  • PhotoLibrary代表系统照片应用对应的相薄,包含照片流和其它自定义的相册
  • PhotosAlbum则对应系统照片应用的照片,包含用设备拍摄的所有照片流。
  • Camera则代表相机的摄像头。

@property (nonatomic, copy) NSArray<NSString *> *mediaTypes;

mediaTypes用于设置相机支持的功能,拍照或者是视频,返回值类型可以是kUTTypeMovie视频和kUTTypeImage拍照

  • kUTTypeMovie包含

const CFStringRef kUTTypeAudiovisualContent ;抽象的声音视频

const CFStringRef kUTTypeMovie ;抽象的媒体格式(声音和视频)

const CFStringRef kUTTypeVideo ;只有视频没有声音

const CFStringRef kUTTypeAudio ;只有声音没有视频

const CFStringRef kUTTypeQuickTimeMovie ;

const CFStringRef kUTTypeMPEG ;

const CFStringRef kUTTypeMPEG4 ;

const CFStringRef kUTTypeMP3 ;

const CFStringRef kUTTypeMPEG4Audio ;

const CFStringRef kUTTypeAppleProtectedMPEG4Audio;

  • kUTTypeImage包含

const CFStringRef kUTTypeImage ;抽象的图片类型

const CFStringRef kUTTypeJPEG ;

const CFStringRef kUTTypeJPEG2000 ;

const CFStringRef kUTTypeTIFF ;

const CFStringRef kUTTypePICT ;

const CFStringRef kUTTypeGIF ;

const CFStringRef kUTTypePNG ;

const CFStringRef kUTTypeQuickTimeImage ;

const CFStringRef kUTTypeAppleICNS const CFStringRef kUTTypeBMP;

const CFStringRef kUTTypeICO;

@property (nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1);

@property (nonatomic) BOOL allowsEditing NS_AVAILABLE_IOS(3_1); // replacement for -allowsImageEditing; default value is NO.

@property (nonatomic) BOOL allowsImageEditing NS_DEPRECATED_IOS(2_0, 3_1);

  • showsCameraControls用于指定拍照时下方的工具栏是否显示
  • allowImageEditing在iOS3.1就已废弃,取而代之的是allowEditing,
  • allowEditing表示拍完照片或者从相册选完照片后,是否跳转到编辑模式对图片裁剪,只有在showsCameraControls为YES时才有效果。

@property (nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraCaptureModePhoto

@property (nonatomic) UIImagePickerControllerCameraDevice cameraDevice NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraDeviceRear

@property (nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode

@property (nonatomic) CGAffineTransform cameraViewTransform NS_AVAILABLE_IOS(3_1); // set the transform of the preview view.

@property (nullable, nonatomic,strong) __kindof UIView *cameraOverlayView NS_AVAILABLE_IOS(3_1); // set a view to overlay the preview view.

当sourceType是camera的时候,这几个属性有效,否则抛出异常。

  • cameraCaptureMode捕捉模式指定的是相机是拍摄照片还是视频,它的枚举类型如下:

NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) {

UIImagePickerControllerCameraCaptureModePhoto,//photo

UIImagePickerControllerCameraCaptureModeVideo//video

};

  • cameraDevice指定拍摄的摄像头位置,是使用前置摄像头还是后置摄像头,它的枚举类型有:

typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {

UIImagePickerControllerCameraDeviceRear,//后摄像头(默认)

UIImagePickerControllerCameraDeviceFront//前摄像头

};

  • cameraFlashMode用于指定闪光灯模式,它的枚举类型如下:

typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {

UIImagePickerControllerCameraFlashModeOff = -1,//关闭闪关灯

UIImagePickerControllerCameraFlashModeAuto = 0,//自动

UIImagePickerControllerCameraFlashModeOn = 1//开启闪关灯

};

  • cameraViewTransform该结构体可以用于指定拍摄时View的一些形变属性,如旋转缩放等。当showsCameraControls为NO,系统的工具栏隐藏时,我们可以自定义背景View赋值给cameraOverlayView添加到拍摄时的预览视图之上。

@property(nonatomic) NSTimeInterval videoMaximumDuration NS_AVAILABLE_IOS(3_1); // default value is 10 minutes.

@property(nonatomic) UIImagePickerControllerQualityType videoQuality NS_AVAILABLE_IOS(3_1);

  • videoMaximumDuration用于设置视频拍摄模式下最大拍摄时长,默认值是10分钟。
  • videoQuality表示拍摄的视频质量设置,默认是Medium即表示中等质量。 videoQuality支持的枚举类型如下:

typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) {

UIImagePickerControllerQualityTypeHigh = 0, // 高清模式

UIImagePickerControllerQualityTypeMedium = 1, //中等质量,适于WIFI传播

UIImagePickerControllerQualityTypeLow = 2, //低等质量,适于蜂窝网络传输

UIImagePickerControllerQualityType640x480 NS_ENUM_AVAILABLE_IOS(4_0) = 3, // VGA 质量

UIImagePickerControllerQualityTypeIFrame1280x720 NS_ENUM_AVAILABLE_IOS(5_0) = 4,//1280*720的分辨率

UIImagePickerControllerQualityTypeIFrame960x540 NS_ENUM_AVAILABLE_IOS(5_0) = 5,//960*540分辨率

};

UIImagePickViewController之类方法

@interface UIImagePickerController : UINavigationController <NSCoding>

+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType; // returns YES if source is available (i.e. camera present)

+ (nullable NSArray<NSString *> *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType; // returns array of available media types (i.e. kUTTypeImage)

+ (BOOL)isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device is available

+ (BOOL)isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device supports flash and torch.

+ (nullable NSArray<NSNumber *> *)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);

  • isSourceTypeAvailable用于判断当前设备是否支持指定的sourceType,可以是照片库/相册/相机.
  • isCameraDeviceAvailable判断当前设备是否支持前置摄像头或者后置摄像头
  • isFlashAvailableForCameraDevice是否支持前置摄像头闪光灯或者后置摄像头闪光灯
  • availableMediaTypesForSourceType方法返回所特定的媒体如相册/图片库/相机所支持的媒体类型数组,元素值可以是kUTTypeImage类型或者kUTTypeMovie类型的静态字符串,所以是NSString类型的数组
  • availableCaptureModesForCameraDevice返回特定的摄像头(前置摄像头/后置摄像头)所支持的拍摄模式数值数组,元素值可以是UIImagePickerControllerCameraCaptureMode枚举里面的video或者photo,所以是NSNumber类型的数组

UIImagePickViewController之对象方法

- (void)takePicture NS_AVAILABLE_IOS(3_1);

- (BOOL)startVideoCapture NS_AVAILABLE_IOS(4_0);

- (void)stopVideoCapture NS_AVAILABLE_IOS(4_0);

  • takePicture可以用来实现照片的连续拍摄,需要自己自定义拍摄的背景视图来赋值给cameraOverlayView,结合自定义overlayView实现多张照片的采集,在收到代理的didFinishPickingMediaWithInfo方法之后可以启动额外的捕捉。
  • startVideoCapture用来判断当前是否可以开始录制视频,当视频正在拍摄中,设备不支持视频拍摄,磁盘空间不足等情况,该方法会返回NO.该方法结合自定义overlayView可以拍摄多部视频
  • stopVideoCapture当你调用此方法停止视频拍摄时,它会调用代理的imagePickerController:didFinishPickingMediaWithInfo:方法

UIImagePickViewController之代理方法

@protocol UIImagePickerControllerDelegate<NSObject>

@optional

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo NS_DEPRECATED_IOS(2_0, 3_0);

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;

@end

  • imagePickerController:didFinishPickingImage:editingInfo:在iOS3.0中已废弃,不再使用。
  • 当用户取消选取的内容时会调用DidCancel方法,默认实现销毁弹出的视图。
  • 当完成内容的选取时会调用didFinishPickingMediaWithInfo方法,默认info字典的key值可以是以下类型:

UIKIT_EXTERN NSString *const UIImagePickerControllerMediaType; //指定用户选择的媒体类型

UIKIT_EXTERN NSString *const UIImagePickerControllerOriginalImage; // 原始图片

UIKIT_EXTERN NSString *const UIImagePickerControllerEditedImage; // 修改后的图片

UIKIT_EXTERN NSString *const UIImagePickerControllerCropRect; // 裁剪尺寸

UIKIT_EXTERN NSString *const UIImagePickerControllerMediaURL; // 媒体的URL

UIKIT_EXTERN NSString *const UIImagePickerControllerReferenceURL NS_AVAILABLE_IOS(4_1); // 原件的URL

UIKIT_EXTERN NSString *const UIImagePickerControllerMediaMetadata //当数据来源是相机的时候获取到的静态图像元数据,可以使用phtoho框架进行处理

UIImagePickViewControllerC语言函数(保存图片或视频)

UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo);

UIKIT_EXTERN BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) NS_AVAILABLE_IOS(3_1);

UIKIT_EXTERN void UISaveVideoAtPathToSavedPhotosAlbum(NSString *videoPath, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) NS_AVAILABLE_IOS(3_1);

  • UIImageWriteToSavedPhotosAlbum用来保存照片到相册,seletor应该设置为- (void)image:(UIImage )image didFinishSavingWithError:(NSError )error contextInfo:(void )contextInfo;当照片保存到相册完成时,会调用该方法通知你。
  • UIVideoAtPathIsCompatibleWithSavedPhotosAlbum会返回布尔类型的值判断该路径下的视频能否保存到相册,视频需要先存储到沙盒文件再保存到相册,而照片是可以直接从代理完成的回调info字典里面获取到。
  • UISaveVideoAtPathToSavedPhotosAlbum用来保存视频到相册,seletor应该设置为- (void)video:(NSString )videoPath didFinishSavingWithError:(NSError )error contextInfo:(void )contextInfo;当视频保存到相册或出错时会调用该方法通知你。
  • 这三个方法一般是在代理的完成方法didFinishPickingMediaWithInfo里面配合使用。

以上便是系统UIImagePickViewController的所有属性和方法的简单介绍

问题解决方案

由于使用设置allowEditing = YES属性后,开启摄像头拍照后直接进入系统自定义的裁剪界面,但是在这个界面,从摄像头拍摄过来的照片无法拖动裁剪,仅仅从相册选择过来的照片是可以拖动进行裁剪的,那么我们就决定裁剪界面不使用系统自带的,而自定义一个裁剪界面.

在UIImagePickViewController的代理方法里

#pragma UIImagePickerController Delegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

UIImage *portraitImg = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

YYImageClipViewController *imgClipVC = [[YYImageClipViewController alloc] initWithImage:portraitImg cropFrame:CGRectMake(0, 100.0f, self.view.frame.size.width, self.view.frame.size.width) limitScaleRatio:3.0];

imgClipVC.delegate = self;

[picker pushViewController:imgClipVC animated:NO];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

[picker dismissViewControllerAnimated:YES completion:nil];

}

HZImageCropperViewController是我自定义的一个裁剪界面,通过这个控制器的两个代理方法,得到裁剪后的照片

- (void)imageClip:(YYImageClipViewController *)clipViewController didFinished:(UIImage *)editedImage

{

//保存图片

NSString *imageFilePath = [UIImage saveImage:editedImage];

//上传七牛服务器

[self upImageFilePath:imageFilePath];

//隐藏裁剪界面

[clipViewController dismissViewControllerAnimated:YES completion:nil];

}

- (void)imageClipDidCancel:(YYImageClipViewController *)clipViewController

{

[clipViewController dismissViewControllerAnimated:YES completion:nil];

}

下面附上一个demo,里面包含裁剪界面的源代码,可供大家参考

自定义裁剪界面demo

 

iOS-拍照后裁剪,不可拖动照片的问题的更多相关文章

  1. android 开发 实现一个进入相机拍照后裁剪图片或者进入相册选中裁剪图片的功能

    实现思维路径: 以进入相机拍照的思维路线为例子: 1.进入app 2.判断之前是否保存头像,如果有就显示历史图像 (下面代码中在getOldAvatar();方法中执行这个逻辑) 3.点击更换图像的B ...

  2. Android 从本地图库或拍照后裁剪图片并设置头像

    在QQ和微信等应用都会有设置头像,一般都是从本地图库选取或相机拍照,然后再截图自己喜欢的部分,然后设置.最后一步把截取好的图片再保存到本地,来保存头像.为了大家使用方便,我把自己完整的代码贴出来,大家 ...

  3. 手机调用系统的拍照和裁剪功能,假设界面有输入框EditText,在一些手机会出现点击EditText会弹出输入法,却不能输入的情况。

    1. 拍照裁剪后 点击EditText会弹出输入法,却不能输入.可是点击点一EdtiText就能够输入了,所以我就写了一个看不见的EdtiText,切换焦点,这样就攻克了这个奇怪的这问题,应该是and ...

  4. 部分Android或IOS手机拍照后照片被旋转的问题

    1.我们平时手机拍的照片,传到电脑后,使用Photoshop或者其它图片浏览工具打开时,发现图片是被转过的.可是Windows上预览却是正的.其实原因是部分Android或IOS手机拍照后,将图片角度 ...

  5. 部分Android手机拍照后照片被旋转的解决方案

      在部分Android手机(如MT788.Note2)上,使用Camera拍照以后,得到的照片会被自动旋转(90°.180°.270°),这个情况很不符合预期.仔细分析了一下,因为照片属性中是存储了 ...

  6. iOS 拍照中加入GPS和具体地理位置

    最近有一个需求,要求用手机拍个照片,并切需要拍摄时间,拍摄gps,拍摄具体街道信息. 首先要感谢PhotoGPSdemo的作者,你可以到这里下载demo http://www.cocoachina.c ...

  7. iOS拍照图片旋转的问题

    很久之前,遇到了这种情况,iOS某端拍照上传到服务器,其他iOS端从服务器下载该照片展示,发现图片逆时针旋转了90度.当时百度了一下,找到一段代码修正image方向,问题解决了,但没有深入理解底层原理 ...

  8. 图片上传前 压缩,base64图片压缩 Exif.js处理ios拍照倒置等问题

    曾写过在前端把图片按比例压缩不失真上传服务器的前端和后台,可惜没有及时做总结保留代码,只记得js利用了base64位压缩和Exif.js进行图片处理,还有其中让我头疼的ios拍照上传后会倒置等诸多问题 ...

  9. Android SDK4/5/6/7,相册、拍照及裁剪功能及遇见的坑

    保存照片和视频到系统相册显示- http://blog.csdn.net/chendong_/article/details/52290329 Android 7.0 之拍照与图片裁剪适配-http: ...

随机推荐

  1. Windows 的命令行安装Scoop程序管理工具

    传送门: # 官网 http://scoop.sh/ # github https://github.com/lukesampson/scoop window中快速安装: 必须使用powershell ...

  2. 8. svg学习笔记-文本

    毫无疑问,文本也是svg中组成的重要部分,在svg中,用<text>元素来创建文本,文本的使用格式如下: <text x="20" y="30" ...

  3. windbg调试子进程

    windbg 调试子进程 学习过程中遇到了一个从前未调试过的情景:我正在调试的进程通过CreateProcessW创建了一个子进程,我需要去了解子进程中发生的行为. 那么怎么去调试呢?OD 就有点麻烦 ...

  4. Pythonic是什么?

    Python 之禅之中有这样几句话: 优美胜于丑陋(Python 以编写优美的代码为目标) 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似) 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂 ...

  5. python基本数据类型之------列表

    一.列表----list 列表是有序的,列表元素可以被修改 =================list之灰魔法================ 1.列表格式: 中括号括起来, 逗号分隔每个元素, 列表 ...

  6. LeetCode算法题-N-ary Tree Level Order Traversal(Java实现)

    这是悦乐书的第225次更新,第238篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第92题(顺位题号是429).给定n-ary树,返回其节点值的级别顺序遍历.(即,从左到 ...

  7. Elixir 单元测试

    概述 elixir 中自带了单元测试框架 ExUnit ,其中提供单元测试的一系列,主要包含以下模块: ExUnit: 单元测试框架 ExUnit.Assertions: 断言 ExUnit.Case ...

  8. Angular四大核心特性

    Angular四大核心特性 Angular四大核心特性理论概述 MVC模式:它目的是为了分离视图.模型和控制器而设计出来的:其中数据模型用来储存数据,视图用来向用户展示应用程序,控制器充当模型和视图之 ...

  9. [matlab] 19.matlab 基础几何学

    polyshape  函数可创建由二维顶点定义的多边形,并返回具有描述其顶点.实心区域和孔的各种属性的 polyshape 对象.例如,pgon = polyshape([0 0 1 1],[1 0 ...

  10. Doc2vec实现原理

    论文来源:https://www.eecs.yorku.ca/course_archive/2016-17/W/6412/reading/DistributedRepresentationsofSen ...