UIImageView获取正在显示的图片的位置

22

我有一个显示UIImage的UIImageView。

UIImage可能会更改为不同大小的其他UIImage,并且UIImage内部的位置和大小将根据其更改。

我的问题是,我试图添加一个视图,该视图将位于始终更改的UIImage的末尾,但我能够获得的只是UIImageView的框架(始终保持全屏状态)。

如何获取当前显示UIImage的“frame”?


没有直接的API可以获取这些信息。您需要根据图像视图的框架、图像大小和图像视图的“contentMode”自行计算。 - rmaddy
@rmaddy,那听起来像是一个非常难以解释的事情。有没有更简单的方法可以黑进去呢? - Asaf Nevo
你可以使用Imageview.image.size.width/height来获取宽度和高度。虽然我不知道origin.x和y属性的含义。 - Eyeball
让我们这样开始,请发布您的代码,展示如何将图像加载到ImageView中。 - chewy
5个回答

27

Swift 4.2 & 5.0

-->

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
}

我如何使用这个来截取屏幕上仅图片的截图? - user5306470

25

以下将回答您的问题,假设您的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);
}

为了更好地说明三种内容模式之间的差异,请参见下面:

输入图像描述


这个解决方案是否假定使用 UIViewContentModeScaleAspectFit 而不是 UIViewContentModeScaleAspectFill?如果您使用了 UIViewContentModeScaleAspectFill,则不需要进行任何计算。 - rmaddy
谢谢,是的,当然是AspectFit。但是,如果需要使用AspectFill,您还需要进行一些计算,因为图像可能会在顶部或左侧被裁剪,以防止它不适合UIImageView而改变其宽度/高度比例。这就是AspectFill和ScaleToFill之间的区别。 - Marcus
@Marcus 我不确定我理解了你的评论。如果您使用了 AspectFillScaleToFill,那么在这些情况下不需要进行任何计算,因为它们都将填充图像视图。两者之间的区别仅在于缩放方式。前者会缩放图像,直到整个图像视图被填满,并保持纵横比,这意味着图像可能超出框架,而后者将拉伸图像以填充图像视图,而不保持纵横比,因此整个图像将可见。 - Pavan
也许我在考虑返回ImageView中可见部分图像的矩形。 - Pavan

9
我建议使用内置函数AVMakeRectWithAspectRatio。
func AVMakeRectWithAspectRatioInsideRect(_ aspectRatio: CGSize, _ boundingRect: CGRect) -> CGRect

参数:

aspectRatio:
您想要保持的宽高比(纵横比)。

boundingRect: 您想要适合的边界矩形。

返回值: 返回一个缩放后的CGRect,该CGRect保持由aspectRatio指定的纵横比,并适合于bounding Rect中。

let boundingBox = AVMakeRectWithAspectRatioInsideRect(backgroundImage.size, frame)


6

基于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...
}

4

Swift 3.0

虽然有些晚了,但可能对未来的某些人有所帮助。苹果iOS提供了非常简单且内置的解决方案,只需要:

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

这样做就可以了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接