UIImageView получает позицию показа изображения

У меня есть UIImageView, который показывает UIImage.

UIImage может измениться на другой UIImage разного размера, а положение и размер UIImage внутри изменятся в соответствии с ним.

Моя проблема в том, что я пытаюсь добавить представление, которое будет в конце UIImage (которое меняет все время), и все, что я могу получить, это кадр UIImageView (который постоянно остается на весь экран).

Как я могу получить "фрейм" текущего отображения UIImage?

Ответ 1

Следующее ответит на ваш вопрос, предполагая, что ваш UIImageView использует UIViewContentModeAspectFit:

Вы должны оценить размер изображения изображения внутри UIImageView. Это зависит от того, как вы устанавливаете contentMode. Согласно вашему описанию, я предполагаю, что вы используете UIViewContentModeAspectFit. Полученное изображение также будет центрировано в UIImageView, поэтому вы также должны учитывать это для расчета.

-(CGRect )calculateClientRectOfImageInUIImageView:(UIImageView *)imgView
{
    CGSize imgViewSize=imgView.frame.size;                  // Size of UIImageView
    CGSize imgSize=imgView.image.size;                      // Size of the image, currently displayed

    // Calculate the aspect, assuming imgView.contentMode==UIViewContentModeScaleAspectFit

    CGFloat scaleW = imgViewSize.width / imgSize.width;
    CGFloat scaleH = imgViewSize.height / imgSize.height;
    CGFloat aspect=fmin(scaleW, scaleH);

    CGRect imageRect={ {0,0} , { imgSize.width*=aspect, imgSize.height*=aspect } };

    // Note: the above is the same as :
    // CGRect imageRect=CGRectMake(0,0,imgSize.width*=aspect,imgSize.height*=aspect) I just like this notation better

    // Center image

    imageRect.origin.x=(imgViewSize.width-imageRect.size.width)/2;
    imageRect.origin.y=(imgViewSize.height-imageRect.size.height)/2;

    // Add imageView offset

    imageRect.origin.x+=imgView.frame.origin.x;
    imageRect.origin.y+=imgView.frame.origin.y;

    return(imageRect);
}

Для лучшей иллюстрации различий между тремя режимами содержимого см. ниже:

enter image description here

Ответ 2

Swift 4.2 и 5.0

func calculateRectOfImageInImageView(imageView: UIImageView) -> CGRect {
        let imageViewSize = imageView.frame.size
        let imgSize = imageView.image?.size

        guard let imageSize = imgSize else {
            return CGRect.zero
        }

        let scaleWidth = imageViewSize.width / imageSize.width
        let scaleHeight = imageViewSize.height / imageSize.height
        let aspect = fmin(scaleWidth, scaleHeight)

        var imageRect = CGRect(x: 0, y: 0, width: imageSize.width * aspect, height: imageSize.height * aspect)
        // Center image
        imageRect.origin.x = (imageViewSize.width - imageRect.size.width) / 2
        imageRect.origin.y = (imageViewSize.height - imageRect.size.height) / 2

        // Add imageView offset
        imageRect.origin.x += imageView.frame.origin.x
        imageRect.origin.y += imageView.frame.origin.y

        return imageRect
    }

Swift 3.0

// MARK: - Create Rect
func calculateRectOfImageInImageView(imageView: UIImageView) -> CGRect {
    let imageViewSize = imageView.frame.size
    let imgSize = imageView.image?.size

    guard let imageSize = imgSize, imgSize != nil else {
        return CGRect.zero
    }

    let scaleWidth = imageViewSize.width / imageSize.width
    let scaleHeight = imageViewSize.height / imageSize.height
    let aspect = fmin(scaleWidth, scaleHeight)

    var imageRect = CGRect(x: 0, y: 0, width: imageSize.width * aspect, height: imageSize.height * aspect)
    // Center image
    imageRect.origin.x = (imageViewSize.width - imageRect.size.width) / 2
    imageRect.origin.y = (imageViewSize.height - imageRect.size.height) / 2

    // Add imageView offset
    imageRect.origin.x += imageView.frame.origin.x
    imageRect.origin.y += imageView.frame.origin.y

    return imageRect
}

Для Swift <3.0

Вот вышеупомянутый метод в Swift. Опять же, если предположить, что contentMode установлен в .ScaleAspectFit Если нет изображений на данном imageView CGRectZero будет возвращено.

func calculateRectOfImageInImageView(imageView: UIImageView) -> CGRect {
    let imageViewSize = imageView.frame.size
    let imgSize = imageView.image?.size

    guard let imageSize = imgSize where imgSize != nil else {
        return CGRectZero
    }

    let scaleWidth = imageViewSize.width / imageSize.width
    let scaleHeight = imageViewSize.height / imageSize.height
    let aspect = fmin(scaleWidth, scaleHeight)

    var imageRect = CGRect(x: 0, y: 0, width: imageSize.width * aspect, height: imageSize.height * aspect)
    // Center image 
    imageRect.origin.x = (imageViewSize.width - imageRect.size.width) / 2
    imageRect.origin.y = (imageViewSize.height - imageRect.size.height) / 2

    // Add imageView offset
    imageRect.origin.x += imageView.frame.origin.x
    imageRect.origin.y += imageView.frame.origin.y

    return imageRect
}

Ответ 3

Я рекомендую использовать встроенную функцию AVMakeRectWithAspectRatio.

func AVMakeRectWithAspectRatioInsideRect(_ aspectRatio: CGSize, _ boundingRect: CGRect) -> CGRect

Параметры:

AspectRatio:
Отношение ширины и высоты (соотношение сторон), которое вы хотите сохранить.

boundingRect:  Ограничивающий прямоугольник, в который вы хотите поместиться.

Возвращаемое значение Возвращает масштабированный CGRect, который поддерживает соотношение сторон, указанное aspectRatio, которое находится в пределах ограничивающего Rect.

let boundingBox = AVMakeRectWithAspectRatioInsideRect (backgroundImage.size, frame)

Ответ 4

Основываясь на удивительно простом решении от Janusz, вот что я сделал:

let visibleRect = AVMakeRect(aspectRatio: CGSize(width: image.size.width, height: image.size.height), insideRect: self.frame)
if visibleRect.contains(point) {
    // Do something great here...
}

Ответ 5

Swift 3.0

Я знаю его довольно поздно, но может помочь кому-то в будущем. Это очень простое и встроенное решение, предоставляемое iOS. Просто нужно:

import AVFoundation
let imageRect = AVMakeRect(aspectRatio: image.size, insideRect: self.imageView.bounds)