Swift UIImageView 拉伸纵横比

30

UIImageView对图像大小的渲染存在问题。使用“等比例缩放”选项时,如果UIImageView是正方形,则图像在正确的宽高比下显示,未覆盖区域将透明显示。

//Image is Square & Correct Size
var imageView = UIImageView(frame: CGRectMake(0, 50, 320, 320))
imageView.clipsToBounds = true
imageView.contentMode = UIViewContentMode.ScaleAspectFit

//Image is Rectangle & Incorrect Size
var imageView = UIImageView(frame: CGRectMake(0, 50, 320, 450))
imageView.clipsToBounds = true
imageView.contentMode = UIViewContentMode.ScaleAspectFit

UIImageView需要触及屏幕的边缘,并在屏幕顶部和底部留有透明空间,图像内部需要保持其原始比例而不是拉伸变高。我附加了两张图片,展示了UIImageView内部图像的渲染情况。

具有正确纵横比的ImageView 具有错误纵横比的ImageView

6个回答

46

我向UIImageView添加了自动调整大小的面具,现在它显示出正确的比例。

imageView.autoresizingMask = UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleWidth
imageView.contentMode = UIViewContentMode.ScaleAspectFit

这个答案对我很有帮助:使用AVCaptureSession sessionPreset = AVCaptureSessionPresetPhoto拍摄的照片被拉伸了,因为我使用的是通过手机相机拍摄的图像。


8
imageView.autoresizingMask = [.flexibleTopMargin, .flexibleHeight, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin, .flexibleWidth]这行代码是 Swift 3 的语法,它设置了一个名为 "autoresizingMask" 的属性,该属性的值是一个包含多个选项的数组。这些选项指定了图像视图在自动调整大小时应该如何调整其边距和尺寸。 - Markymark
1
@George Grover 这个回答已经过时了,请更新一下。 - iPhone 7

24

您的代码的Swift 3版本:

imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin]
imageView.contentMode = .scaleAspectFit // OR .scaleAspectFill
imageView.clipsToBounds = true

23

我曾经遇到过同样的问题,解决方法是确保在设置内容模式之后设置imageView图像,例如:

    self.imageView.contentMode = UIViewContentMode.ScaleAspectFit
    self.imageView.image = imageChosen

干杯


2
解决了我的问题。真是荒谬,我花了三个小时来解决这个错误,结果原来是这个解决方案。 - Samuel Noyes

7
UIViewContentMode.ScaleAspectFit的预期行为是这样的,来自文档:

UIViewContentModeScaleAspectFit

按比例缩放内容以适应视图的大小。视图边界上任何剩余的区域都是透明的。

从您所描述的情况来看,似乎需要使用UIViewContentMode.ScaleAspectFill

UIViewContentModeScaleAspectFill

将内容缩放以填充视图的大小,但可能会裁剪部分内容以填充视图的边界。


我希望图片适应盒子,例如当盒子变高时,两侧接触边缘,顶部和底部仍保留透明空间。ScaleAspectFill无法实现这种效果,您会建议如何强制它接触两侧但不接触顶部和底部? - George Grover
好的,我以为你是说你不想要透明度。抱歉我误解了你。 - Cezar
抱歉,我没有恰当地解释清楚 - 我更新了我的问题以澄清。你有任何想法为什么图像会垂直增长而不是水平增长吗? - George Grover
不行。而且我刚刚使用你的代码和图片设置了一个示例项目,问题并没有发生。奇怪。 - Cezar

2

Swift 5

您只能将UIView.ContentMode.scaleAspectFit应用于像这样的UIImageView

        let logoImage:UIImage = UIImage(named: "my_logo")!

        let logoImageView = UIImageView(image: logoImage)

        logoImageView.contentMode = UIView.ContentMode.scaleAspectFit

        return logoImageView

1

这里有一个非常好的解决方案在这里:olearyj234提供。
它帮助了我很多。建议看一下。此外,这是他的Swift 4和Xcode 9.2代码:

    class ScaledHeightImageView: UIImageView {

    override var intrinsicContentSize: CGSize {

        if let myImage = self.image {
            let myImageWidth = myImage.size.width
            let myImageHeight = myImage.size.height
            let myViewWidth = self.frame.size.width

            let ratio = myViewWidth/myImageWidth
            let scaledHeight = myImageHeight * ratio

            return CGSize(width: myViewWidth, height: scaledHeight)
        }

        return CGSize(width: -1.0, height: -1.0)
    }

}

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