UIImagePicker 允许编辑卡在中心
Posted
技术标签:
【中文标题】UIImagePicker 允许编辑卡在中心【英文标题】:UIImagePicker allowsEditing stuck in center 【发布时间】:2012-09-27 21:16:43 【问题描述】:我有一个 UIImagePicker,它非常适合一种 UIImagePickerControllerSourceTypePhotoLibrary,但是当我使用 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)
];
如您所见,我将它们显示为完全相同,但相机编辑与照片库编辑的行为不同。
【问题讨论】:
【参考方案1】:看起来这种行为只是ios 6中的一个错误......基本上你不能移动编辑框,除非你放大一点,它总是弹回中间。希望他们能尽快解决这个问题。
【讨论】:
我认为这仍然是 iOS 7 中的一个错误 aaa 仍然是 iOS 8 中的一个错误。:( iOS 8.1 也存在同样的 bug 我来自未来,仍然是 iOS 12.0 中的一个 bug 仍然是 iOS 9 中的一个错误。有人找到解决方案了吗?【参考方案2】:谢谢yycking。这extension 有效。除了我在viewDidLayoutSubviews
中添加了方法调用,这样我就不必每次打开图像选择器时都调用它。
这是完整的扩展名
extension UIImagePickerController
open override var childForStatusBarHidden: UIViewController?
return nil
open override var prefersStatusBarHidden: Bool
return true
open override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
fixCannotMoveEditingBox()
func fixCannotMoveEditingBox()
if let cropView = cropView,
let scrollView = scrollView,
scrollView.contentOffset.y == 0
var top: CGFloat = 0.0
if #available(iOS 11.0, *)
top = cropView.frame.minY + self.view.safeAreaInsets.top
else
// Fallback on earlier versions
top = cropView.frame.minY
let bottom = scrollView.frame.height - cropView.frame.height - top
scrollView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: bottom, right: 0)
var offset: CGFloat = 0
if scrollView.contentSize.height > scrollView.contentSize.width
offset = 0.5 * (scrollView.contentSize.height - scrollView.contentSize.width)
scrollView.contentOffset = CGPoint(x: 0, y: -top + offset)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) [weak self] in
self?.fixCannotMoveEditingBox()
var cropView: UIView?
return findCropView(from: self.view)
var scrollView: UIScrollView?
return findScrollView(from: self.view)
func findCropView(from view: UIView) -> UIView?
let width = UIScreen.main.bounds.width
let size = view.bounds.size
if width == size.height, width == size.height
return view
for view in view.subviews
if let cropView = findCropView(from: view)
return cropView
return nil
func findScrollView(from view: UIView) -> UIScrollView?
if let scrollView = view as? UIScrollView
return scrollView
for view in view.subviews
if let scrollView = findScrollView(from: view)
return scrollView
return nil
【讨论】:
【参考方案3】:愚蠢的答案 重置scrollview的contentInset
extension UIImagePickerController
func fixCannotMoveEditingBox()
if let cropView = cropView,
let scrollView = scrollView,
scrollView.contentOffset.y == 0
let top = cropView.frame.minY + self.view.safeAreaInsets.top
let bottom = scrollView.frame.height - cropView.frame.height - top
scrollView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: bottom, right: 0)
var offset: CGFloat = 0
if scrollView.contentSize.height > scrollView.contentSize.width
offset = 0.5 * (scrollView.contentSize.height - scrollView.contentSize.width)
scrollView.contentOffset = CGPoint(x: 0, y: -top + offset)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) [weak self] in
self?.fixCannotMoveEditingBox()
var cropView: UIView?
return findCropView(from: self.view)
var scrollView: UIScrollView?
return findScrollView(from: self.view)
func findCropView(from view: UIView) -> UIView?
let width = UIScreen.main.bounds.width
let size = view.bounds.size
if width == size.height, width == size.height
return view
for view in view.subviews
if let cropView = findCropView(from: view)
return cropView
return nil
func findScrollView(from view: UIView) -> UIScrollView?
if let scrollView = view as? UIScrollView
return scrollView
for view in view.subviews
if let scrollView = findScrollView(from: view)
return scrollView
return nil
然后调用它
imagePickercontroller.fixCannotMoveEditingBox()
【讨论】:
【参考方案4】:这是 Image Picker Controller 的默认行为,您不能更改它。唯一的其他选择是创建自己的裁剪实用程序。查看下面的链接以获取示例:
https://github.com/ardalahmet/SSPhotoCropperViewController
【讨论】:
但是当你从专辑中挑选时它会起作用..没有意义。当它来自相册而不是相机时,为什么你可以移动更多 @Eric 编辑框完全不动,它固定在屏幕中间,您可以缩放图片以适应框。截图,因为你的代码是对的 我会尽快添加屏幕截图,但我的意思是静态框保持静止(这是正确的),但移动的下方图像无法移动,因此编辑框位于图像的顶部区域。如果您滚动到该区域,图像会“弹回”到图像的中心... 这不是默认行为,我相信这是 ios6 中的错误。在以前的 ios 版本上它可以正常工作,但在 ios6 上,当您尝试移动它时,图像会反弹回来。但是,如果您放大一点,它确实会起作用。 @Robert 哦,好吧..这就是我的想法!我想我会一直这样,直到他们更新它..【参考方案5】:我知道,这不是一个好的解决方案,但它确实有效。
我在 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:
方法遍历所有子视图树。
【讨论】:
【参考方案6】:如果您在 info.plist 中将“基于控制器的状态栏外观”设置为 NO,并使用以下方法将状态栏外观设置为浅色
UIApplication.shared.statusBarStyle = .lightContent
或使用任何其他方法,然后只需在呈现图像选择器之前将样式设置为 .default。例如:
imagePicker.allowsEditing = true
imagePicker.sourceType = .photoLibrary
UIApplication.shared.statusBarStyle = .default
present(imagePicker, animated: true, completion: nil)
根据您的需要将源类型更改为 photoLibrary 或相机,并在 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
)
显然这是一个解决方法。希望这会有所帮助。
【讨论】:
【参考方案7】:解决此问题的解决方法是在 info.plist 中添加一个条目,并将“基于控制器的状态栏外观”设置为 NO
【讨论】:
以上是关于UIImagePicker 允许编辑卡在中心的主要内容,如果未能解决你的问题,请参考以下文章
UIImagePicker 无法在 iOS 3.1.3 上执行全屏转换
iPad 问题:使用 UIImagePicker 从视频文件夹中选择视频