Показать представление перед imagePicker - PullRequest
0 голосов
/ 15 мая 2018

В моем приложении пользователь может либо открыть рулон камеры, чтобы выбрать снимок, либо открыть камеру, чтобы сделать один снимок.

В обоих случаях выбранное / сделанное изображение также будет сохранено локально для дальнейшего использования.

Недостатком является то, что операция сохранения обычно останавливает экран до его завершения.

Я нашел анимацию в этом посте и хочу показать ее перед 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, но безрезультатно.

следующий этот похожий вопрос Я посмотрел документацию для cameraOverlayView , но он говорит, что он работает только тогда, когда imagePicker представлен в режиме камеры, что не распространяется на случай, когда Я открываю фотобиблиотеку

Я также недавно пытался использовать обходной путь, то есть я уволил imagePickerController как можно скорее и впоследствии обновил изображение, но это больше не оптимально из-за некоторых изменений в структуре приложения.

EDIT

, чтобы сделать себя более ясным, я еще раз заявлю, что мне нужно: показать анимацию вращения перед в ImagePicker, как только я коснусь фотографии, чтобы выбрать ее, и пока я не закончу сохранение, затем отклонить imagePicker. Я не хочу сначала свернуть сборщик, а затем сохранить его, показывая вертушку на главном экране.

EDIT2 обновил код с новым из ответа. Единственная проблема заключается в том, что, если я не установлю таймер, блесна покажет себя только в конце процесса сохранения на короткое время (проверяется с помощью точек останова). Это приводит к отсутствию анимации в течение пары секунд процесса сохранения и только к краткому появлению вращателя в конце, перед тем как закрыть ImagePicker. Просто установив задержку в 0,1 с, вы сразу же запускаете счетчик, и я получаю ожидаемое поведение (анимация при сохранении). Понятия не имею, почему

1 Ответ

0 голосов
/ 18 мая 2018

Пожалуйста, посмотрите полный пример, где будет отображаться счетчик, пока изображение сохраняется, а после завершения сохранения счетчик будет удален.

    class ViewController: UIViewController {

    /// Image picker controller
    lazy var imagePickerController: UIImagePickerController  = {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary;
        imagePicker.allowsEditing = false
        return imagePicker
    }()

    var spinner: UIActivityIndicatorView?

    @IBAction func imagePickerButton(_ sender: UIButton) {
        self.present(self.imagePickerController, animated: true, completion: nil)
    }
}

// MARK: ImagePicker Delegate to get the image picked by the user
extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        //start animation
        let screenSize: CGRect = UIScreen.main.bounds
        spinner = UIActivityIndicatorView(frame: CGRect(x: screenSize.width/2 - 50, y: screenSize.height/2 - 50, width: 100, height: 100))
        spinner?.isHidden = false
        spinner?.startAnimating()
        spinner?.color = UIColor.black
        self.imagePickerController.view.addSubview(spinner!)

        let image = info[UIImagePickerControllerOriginalImage] as? UIImage
        UIImageWriteToSavedPhotosAlbum(image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)

    }

    @objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {

        spinner?.stopAnimating()
        spinner?.removeFromSuperview()
        spinner  = nil

        self.imagePickerController.dismiss(animated: true, completion: nil)

        if  error == nil {
            let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}
...