UIImagePickerControllerSourceTypePhotoLibraryのタイプに最適なUIImagePickerがありますが、UIImagePickerControllerSourceTypeCameraを使用すると、編集ボックスが画像の中心から移動できません。そのため、画像の高さが幅よりも高い場合、ユーザーは編集ボックスを画像の上部の正方形に移動できません。
なぜこれが当てはまるのか誰もが知っていますか?これは、ソースがライブラリではなくカメラからのものである場合にのみ発生します。
編集:いくつかのコード!!!
if (actionSheet.tag == 2) {
if (buttonIndex == 0) { // Camera
// Check for camera
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) {
// Create image picker controller
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// Set source to the camera
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.allowsEditing = YES;
// Delegate is self
imagePicker.delegate = self;
// Show image picker
[self presentViewController:imagePicker
animated:YES
completion:^(void) {
}];
}
}
else if (buttonIndex == 1) { // Photo Library
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary] == YES) {
// Create image picker controller
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// Set source to the camera
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.allowsEditing = YES;
// Delegate is self
imagePicker.delegate = self;
// Show image picker
[self presentViewController:imagePicker
animated:YES
completion:^(void) {
}];
}
}
ご覧のとおり、まったく同じように表示しますが、カメラの編集はフォトライブラリの編集とは動作が異なります。
この動作はiOS6の単なるバグのようです...基本的に編集ボックスを移動することはできません。少しズームインしない限り、常に中央に戻ります。うまくいけば、彼らはすぐにそれを修正します。
Info.plistで「コントローラーベースのステータスバーの外観を表示する」を「いいえ」に設定し、を使用してステータスバーの外観を明るいものとして設定した場合
UIApplication.shared.statusBarStyle = .lightContent
または他の方法を使用して、画像ピッカーを表示する前に、スタイルを.defaultとして設定するだけです。例:
imagePicker.allowsEditing = true
imagePicker.sourceType = .photoLibrary
UIApplication.shared.statusBarStyle = .default
present(imagePicker, animated: true, completion: nil)
photoLibraryまたはcameraのいずれかとして、必要に応じてソースタイプを変更し、didFinishPickingMediaWithInfoの完了ブロックで次を追加して完了しますブロック。
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
//let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
var pickedImage : UIImage?
if let img = info[UIImagePickerControllerEditedImage] as? UIImage
{
pickedImage = img
}
else if let img = info[UIImagePickerControllerOriginalImage] as? UIImage
{
pickedImage = img
}
dismiss(animated: true, completion: {
UIApplication.shared.statusBarStyle = .lightContent
})}
どうやらこれは同じための回避策です。これが役立つことを願っています。
これは良い解決策ではありませんが、機能します。
IOS8 + iPhone5、iOS9 + iPhone6sPlus、iOS10 + iPhone6、iOS10 + iPhone6sPlusでテストしました。
[〜#〜]注意[〜#〜]:PLImageScrollView
とPLCropOverlayCropView
は[〜#〜]文書化されていない[〜#〜] =クラス。
- (void)showImagePickerControllerWithSourceType:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *imagePickerController = [UIImagePickerController new];
imagePickerController.sourceType = sourceType;
imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
imagePickerController.allowsEditing = YES;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:^{
[self fxxxImagePickerController:imagePickerController];
}];
}
- (void)fxxxImagePickerController:(UIImagePickerController *)imagePickerController {
if (!imagePickerController
|| !imagePickerController.allowsEditing
|| imagePickerController.sourceType != UIImagePickerControllerSourceTypeCamera) {
return;
}
// !!!: UNDOCUMENTED CLASS
Class ScrollViewClass = NSClassFromString(@"PLImageScrollView");
Class CropViewClass = NSClassFromString(@"PLCropOverlayCropView");
[imagePickerController.view eachSubview:^BOOL(UIView *subview, NSInteger depth) {
if ([subview isKindOfClass:CropViewClass]) {
// 0. crop rect position
subview.frame = subview.superview.bounds;
}
else if ([subview isKindOfClass:[UIScrollView class]]
&& [subview isKindOfClass:ScrollViewClass]) {
BOOL isNewImageScrollView = !self->_imageScrollView;
self->_imageScrollView = (UIScrollView *)subview;
// 1. enable scrolling
CGSize size = self->_imageScrollView.frame.size;
CGFloat inset = ABS(size.width - size.height) / 2;
self->_imageScrollView.contentInset = UIEdgeInsetsMake(inset, 0, inset, 0);
// 2. centering image by default
if (isNewImageScrollView) {
CGSize contentSize = self->_imageScrollView.contentSize;
if (contentSize.height > contentSize.width) {
CGFloat offset = round((contentSize.height - contentSize.width) / 2 - inset);
self->_imageScrollView.contentOffset = CGPointMake(self->_imageScrollView.contentOffset.x, offset);
}
}
}
return YES;
}];
// prevent re-layout, maybe not necessary
@weakify(self, imagePickerController);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@strongify(self, imagePickerController);
[self fxxxImagePickerController:imagePickerController];
});
}
[〜#〜] edit [〜#〜]:eachSubview:
メソッドはすべてのサブビューツリーをトラバースします。
これはイメージピッカーコントローラーのデフォルトの動作であり、変更することはできません。他の唯一のオプションは、独自のトリミングユーティリティを作成することです。例については、以下のリンクを確認してください。
愚かな答え
コンテンツをリセットスクロールビューのインセット
#import <objc/runtime.h>
@interface WeakObjectContainer : NSObject
@property (nonatomic, readonly, weak) id object;
@end
@implementation WeakObjectContainer
- (instancetype) initWithObject:(id)object
{
if (!(self = [super init]))
return nil;
_object = object;
return self;
}
@end
@implementation UIImagePickerController (PLUS)
// MARK: - Create a weak stored property in extension
- (id)weakObjectForKey:(const void*)key {
WeakObjectContainer *container = objc_getAssociatedObject(self, key);
return [container object];
}
- (void)setWeakObject:(id)object forKey:(const void*)key {
WeakObjectContainer *container = [[WeakObjectContainer alloc] initWithObject:object];
objc_setAssociatedObject(self, key, container, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// MARK: - Create a weak property for scrollView
- (UIScrollView *)scrollView {
return [self weakObjectForKey:_cmd];
}
- (void)setScrollView:(UIScrollView *)scrollView {
[self setWeakObject:scrollView forKey:@selector(scrollView)];
}
// MARK: - Create a weak property for cropView
- (UIView *)cropView {
return [self weakObjectForKey:_cmd];
}
- (void)setCropView:(UIView *)cropView {
[self setWeakObject:cropView forKey:@selector(cropView)];
}
// MARK: - Fix cannot move editing xox
- (void)fixCannotMoveEditingBox {
if (!self.scrollView || !self.cropView) {
UIView *view = [self view];
self.scrollView = [self findScrollView:view];
self.cropView = [self findCropView:view];
if (self.scrollView && self.cropView) {
CGFloat top = self.cropView.frame.Origin.y;
CGFloat bottom = ({
self.scrollView.frame.size.height - self.cropView.frame.size.height - self.cropView.frame.Origin.y;
});
self.scrollView.contentInset = UIEdgeInsetsMake(top, 0, bottom, 0);
self.scrollView.contentOffset = CGPointMake(0, -1);
}
}
__weak typeof(self) weakself = self;
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
__strong typeof(weakself) strongself = weakself;
[strongself fixCannotMoveEditingBox];
});
}
- (UIScrollView *)findScrollView:(UIView *)view {
if ([view isKindOfClass:[UIScrollView class]]) {
return (UIScrollView *)view;
}
for (UIView *subview in [view subviews]) {
UIScrollView *view = [self findScrollView:subview];
if (view) {
return view;
}
}
return nil;
}
- (UIView *)findCropView:(UIView *)view {
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
CGSize size = [view frame].size;
if (size.width == width && size.height == width) {
return view;
}
for (UIView *subview in [view subviews]) {
UIView *view = [self findCropView:subview];
if (view) {
return view;
}
}
return nil;
}
@end
それからそれを呼ぶ
[imagePickerController fixCannotMoveEditingBox];