UIImagePickerController裁剪图像rect不正确

时间:2018-02-14 10:58:42

标签: ios uiimagepickercontroller

我有UIViewController来保存图片选择器:

let picker = UIImagePickerController()

我将图像选择器称为:

private func showCamera() {
    picker.allowsEditing = true
    picker.sourceType = .camera
    picker.cameraCaptureMode = .photo
    picker.modalPresentationStyle = .fullScreen
    present(picker, animated: true, completion: nil)
}

当我完成时,我得到一个代表回调:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    DispatchQueue.main.async {
        if let croppedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
            self.imageView.contentMode = .scaleAspectFill
            self.imageView.image = croppedImage
            self.dismiss(animated:true, completion: nil)
        }
    }
}

我在拍摄图像后得到裁剪用户界面,在视频中你可以看到行为:

https://youtu.be/OaJnsjrlwF8

如您所见,我无法将缩放的矩形滚动到底部或顶部。此行为在iOS 10/11上可在多个设备上重现。

有没有办法通过UIImagePickerController来解决这个问题?

1 个答案:

答案 0 :(得分:0)

不,这个组件已经被淘汰了很长一段时间了。不仅这个有定位的,而且裁剪的矩形通常是不正确的(垂直偏差约20px)。

似乎Apple没有兴趣修复它,你应该创建自己的。这不是太多的工作。首先创建一个接受滚动视图并在滚动视图上显示图像的屏幕。然后确保缩放和平移工作(甚至可能是旋转),这应该很快完成。

然后通过使用视图快照实现最快完成的裁剪部分:

以下内容将从图像视图中创建图像:

    func snapshotImageFor(view: UIView) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        view.layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

然后在你的视图控制器中你可以做这个小技巧:

    func createSnapshot(inFrame rect: CGRect) -> UIImage? {
        let temporaryView = UIView(frame: rect) // This is a view from which the snapshot will occure
        temporaryView.clipsToBounds = true
        view.addSubview(temporaryView) // We want to put it into hierarchy

        guard let viewToSnap = scrollViewContainer else { return nil } // We want to use the superview of the scrollview because using scroll view directly may have some issues.

        let originalImageViewFrame = viewToSnap.frame // Preserve previous frame
        guard let originalImageViewSuperview = viewToSnap.superview else { return nil } // Preserve previous superview
        guard let index = originalImageViewSuperview.subviews.index(of: viewToSnap) else { return nil } // Preserve view hierarchy index

        // Now change the frame and put it on the new view
        viewToSnap.frame = originalImageViewSuperview.convert(originalImageViewFrame, to: temporaryView)
        temporaryView.addSubview(viewToSnap)

        // Create snapshot
        let croppedImage = snapshotImageFor(view: temporaryView)

        // Put everything back the way it was
        viewToSnap.frame = originalImageViewFrame // Reset frame
        originalImageViewSuperview.insertSubview(viewToSnap, at: index) // Reset superview
        temporaryView.removeFromSuperview() // Remove the temporary view

        self.croppedImage = croppedImage

        return croppedImage
    }

这个程序有一些缺点,例如在主线程上执行所有操作,但对于您的特定过程,这应该不是问题。

您可能在某些时候需要对图像输出大小进行一些控制。您可以通过修改快照映像以包含自定义比例来实现最简单的操作:

func snapshotImageFor(view: UIView, scale: CGFloat = 0.0) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, scale)

然后你会打电话给snapshotImageFor(view: view, scale: expectedWidth/view.bounds.width)