【发布时间】:2018-05-15 06:39:45
【问题描述】:
在我的应用程序中,用户可以打开相机胶卷选择一张照片,也可以打开相机自己直接拍照。
在这两种情况下,所选/拍摄的照片也将保存在本地以供进一步参考。
缺点是保存操作通常会冻结屏幕直到完成。
我找到了一个动画 in this post,我想在 imagePickerController 前面显示它,但我做不到。
class SinglePageViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate, UINavigationBarDelegate {
var spinner: UIActivityIndicatorView?
lazy var showCameraImagePickerController: UIImagePickerController = {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
return imagePicker
}()
lazy var showPhotoImagePickerController: UIImagePickerController = {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
return imagePicker
}()
@IBOutlet weak var photoButton: UIButton!
@IBAction func onPhotoButton(_ sender: Any) {
self.present(self.showCameraImagePickerController, animated: true, completion: nil)
}
@IBOutlet weak var galleryButton: UIButton!
@IBAction func onGalleryButton(_ sender: Any) {
self.present(self.showPhotoImagePickerController, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
//start animation
let screenSize: CGRect = UIScreen.main.bounds
spinner = UIActivityIndicatorView(frame: CGRect(x: screenSize.width / 2 - 150, y: screenSize.height / 2 - 150, width: 300, height: 300))
spinner?.isHidden = false
spinner?.startAnimating()
spinner?.color = UIColor.red
switch picker {
case showCameraImagePickerController:
// snap pic, save to doc, save to album
self.showCameraImagePickerController.view.addSubview(spinner!)
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false, block: { _ in
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
if self.saveImage(imageName: "\(self.titleLabel.text!).png", image: image) {
// additionally save to photo album
UIImageWriteToSavedPhotosAlbum(image!, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
print("saved \(self.titleLabel.text!).png")
self.imageView.image = image
}
})
case showPhotoImagePickerController:
//switch pic, save to doc. no album
self.showPhotoImagePickerController.view.addSubview(spinner!)
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false, block: { _ in
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
if self.saveImage(imageName: "\(self.titleLabel.text!).png", image: image) {
print("saved new \(self.titleLabel.text!).png")
self.imageView.image = image
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
self.showPhotoImagePickerController.dismiss(animated: true, completion: nil)
} else {
self.spinner?.stopAnimating()
self.spinner?.removeFromSuperview()
self.spinner = nil
self.showPhotoImagePickerController.dismiss(animated: true, completion: nil)
}
})
default:
return
}
}
@objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
spinner?.stopAnimating()
spinner?.removeFromSuperview()
spinner = nil
self.showCameraImagePickerController.dismiss(animated: true, completion: nil)
}
func saveImage(imageName: String, image: UIImage?) -> Bool {
//create an instance of the FileManager
let fileManager = FileManager.default
//get the image path
let imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imgDir + imageName)
print(imagePath)
//get the image we took with camera
let image = rotateImage(image: image!)
//get the PNG data for this image
let data = UIImagePNGRepresentation(image)
//store it in the document directory
if fileManager.createFile(atPath: imagePath as String, contents: data, attributes: nil) {
newItem?.image = true
return true
} else {
print("error while saving")
return false
}
}
}
如您所见,我尝试使用bringSubView(toFront:) 和zPosition,但没有结果。
在 this similar question 之后,我查看了 cameraOverlayView 的文档,但它说它仅在 imagePicker 以相机模式呈现时才有效,这不包括我打开照片库时的情况
我最近还尝试使用一种解决方法,这意味着我会尽快关闭 imagePickerController 并在之后更新图像,但这不再是最佳选择,因为应用程序的结构发生了一些变化。
编辑
为了让自己更清楚,我将再次说明我需要什么:在图像选择器前面显示微调器动画,只要我点击一张照片以选择它,直到我完成保存,然后关闭 imagePicker。 我不想想先关闭选择器,然后在主视图中显示微调器时保存。
EDIT2 用答案中的新代码更新了代码。唯一的问题是,如果我不设置计时器,则微调器只会在保存过程结束时短暂显示(用断点检查)。 这导致在保存过程的几秒钟内没有动画,并且在关闭 imagePicker 之前,最后旋转器的短暂幻影。 只需延迟 0.1 秒就会立即触发微调器,我会得到预期的行为(保存时的动画)。 不知道为什么
【问题讨论】:
-
代码看起来不错。尝试将
backgroundColor设置为spinnerView并检查它在DebugViewHierarchy中的位置。 -
我能够验证
spinnerView已创建。如果我在成功保存时不删除它,当 imagePicker 关闭时我可以看到它。只需将它移到前面 -
嗨@Kamran 很抱歉打扰你,但你知道如何解决我的问题吗?我会提供赏金,但我的积分太少了..
-
让我试试。微调器类与另一个问题中的相同?
-
其实我改成了更简单的
mySpinner = UIActivityIndicatorView(frame: CGRect(x: screenSize.width/2 - 50, y: screenSize.height/2 - 50, width: 100, height: 100)) mySpinner?.isHidden = false mySpinner?.startAnimating() mySpinner?.color = UIColor.black self.view.addSubview(mySpinner!)
标签: swift animation view uiimagepickercontroller