Как да променя режима на съдържанието на uiimageview по време на изпълнение?

Имам UIViewController с UIImageView, ако докосна екрана, искам UIImageView да промени своя contentMode. Но разбрах, че това не работи с някои изображения, главно тези от AVCaptureSession.

Екранни снимки: Попълване на аспект

въведете описание на изображението тук

Съотношение

въведете описание на изображението тук

Открих също, че работи добре, когато променя ориентацията на устройството на пейзажна и обратно. Но когато докосна екрана, отново не работи.

Напасване на аспекта след промяна на ориентацията към пейзаж и обратно (ето как искам да изглежда всеки път при напасване на аспект)

въведете описание на изображението тук

Моят код:

CameraController:

class CameraController: UIViewController {

private var captureSession = AVCaptureSession()
private var captureDevice: AVCaptureDevice!
private var capturePhotoOutput = AVCapturePhotoOutput()
private var previewLayer: AVCaptureVideoPreviewLayer!

override func viewDidLoad() {
    super.viewDidLoad()

    setupCaptureSession()
    setupCaptureDevice()
    setupInputAndOutput()
    setupPreviewLayer()
    startCaptureSession()

    setupLayout()
}

private func setupCaptureSession() {
    captureSession.sessionPreset = .photo
}

private func setupCaptureDevice() {
    guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices.first else { return }

    captureDevice = device
}

private func setupInputAndOutput() {
    do {
        let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.addInput(captureDeviceInput)

        let captureSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
        capturePhotoOutput.setPreparedPhotoSettingsArray([captureSettings], completionHandler: nil)
        captureSession.addOutput(capturePhotoOutput)
    } catch {
        print(error.localizedDescription)
    }
}

private func setupPreviewLayer() {
    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.videoGravity = .resizeAspectFill
    previewLayer.connection?.videoOrientation = .portrait
    previewLayer.frame = view.frame
    view.layer.insertSublayer(previewLayer, at: 0)
}

private func startCaptureSession() {
    captureSession.startRunning()
}

private func setupLayout() {
    let captureButton = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
    captureButton.backgroundColor = .white
    captureButton.layer.cornerRadius = 22
    captureButton.addTarget(self, action: #selector(didPressCaptureButton), for: .touchUpInside)
    captureButton.center.x = view.center.x
    captureButton.center.y = view.frame.height - 50
    view.addSubview(captureButton)
}

@objc private func didPressCaptureButton() {
    let settings = AVCapturePhotoSettings()
    capturePhotoOutput.capturePhoto(with: settings, delegate: self)
}
}

extension CameraController: AVCapturePhotoCaptureDelegate {

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    guard let imageData = photo.fileDataRepresentation() else { return }
    guard let image = UIImage(data: imageData) else { return }

    print("Image size: ", image.size)

    let previewController = PreviewController()
    previewController.image = image
    present(previewController, animated: true, completion: {
        self.captureSession.stopRunning()
    })
}
}

PreviewController:

class PreviewController: UIViewController {

var imageView: UIImageView!
var image: UIImage!

override func viewDidLoad() {
    super.viewDidLoad()

    setupImageView()
}

func setupImageView() {
    imageView = UIImageView(image: image)
    imageView.contentMode = .scaleAspectFill
    view.addSubview(imageView)
    imageView.addConstraintsToFillSuperview()
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let contentMode: UIViewContentMode = imageView.contentMode == .scaleAspectFill ? .scaleAspectFit : .scaleAspectFill
    imageView.contentMode = contentMode
}

}

Какво правя грешно тук?

Благодаря ти!


person Tomas Kypry    schedule 03.06.2018    source източник
comment
Вместо да променяте режима на изглед на изображението, какво ще стане, ако замените изгледа на изображението с друг?   -  person matt    schedule 03.06.2018
comment
опитайте да извикате layoutSubViews(), след като промените режима на съдържание.   -  person Elhoej    schedule 03.06.2018
comment
layoutSubviews() е това, което наричате, когато работите в UIView. Но кодът ви изглежда като от UIViewController, така че правилният метод за извикване е view.setNeedsLayout().   -  person dfd    schedule 03.06.2018
comment
layoutSubview() нито view.setNeedsLayout() не работят :(   -  person Tomas Kypry    schedule 03.06.2018
comment
@matt Добавянето на друг UIImageView и промяната на неговото свойство „isHidden“ работи. Но просто не ми се струва правилният начин да направите това.   -  person Tomas Kypry    schedule 03.06.2018
comment
На какво основание го казваш? Струва ми се много по-правилно, отколкото да се опитвам да променя режима на съдържанието. Може да опитате да промените режима на съдържание и след това да кажете setNeedsDisplay, но като цяло идеята за промяна на режима на съдържание на изглед на изображение, когато той вече показва изображение, се чувства отвратителна. Фактът, че смятате, че трябва да направите това, сам по себе си е лоша миризма, според мен.   -  person matt    schedule 03.06.2018
comment
Също така имах някои проблеми с обновяването на UIImageView, когато тяхното съдържание или режим на съдържание се промени; така че може би размяната на изгледи на изображения е просто най-лесният изход.   -  person matt    schedule 10.06.2018


Отговори (1)


Можете да промените ImageView contentMode по време на изпълнение с:

    self.imageView.contentMode = newContentMode
    self.imageView.setNeedsDisplay()
person Amir Ardalan    schedule 08.09.2020