UIImageView 保持宽高比,但适合宽度

UIImageView keep aspect ratio, but fit to width

我有一个固定宽度和高度的 UIImageView。我不想更改 UIImageView 的框架。我想让它保存一个图像,我保持纵横比并适合宽度,让图像对于 UIImageView 的框架来说要么太高,要么太短。像这样:

红色的是UIImageView的框架。灰色是显示的实际图像。

我认为最好的方法是调整 imageView 的模式(Aspect Fill、Aspect Width 等),这是基于图像的宽度和高度之间的比率

if image.width > image.height {
    imageView.contentMode = UIViewContentModeScaleAspectFit
    //since the width > height we may fit it and we'll have bands on top/bottom
} else {
  imageView.contentMode = UIViewContentModeScaleAspectFill
  //width < height we fill it until width is taken up and clipped on top/bottom
}

UIViewContentModeScaleAspectFit

Scales the content to fit the size of the view by maintaining the aspect ratio. Any remaining area of the view’s bounds is transparent.

UIViewContentModeScaleAspectFill

Scales the content to fill the size of the view. Some portion of the content may be clipped to fill the view’s bounds.

我还没有测试过,但在我的脑海中,这似乎是正确的

我认为您需要将图像纵横比与 UIImageView 本身的纵横比进行比较:

private func updateUI() {
    guard let image = image else { return }
    let viewAspectRatio = self.bounds.width / self.bounds.height
    let imageAspectRatio = image.size.width / image.size.height
    if viewAspectRatio > imageAspectRatio {
        self.contentMode = .scaleAspectFill
    } else {
        self.contentMode = .scaleAspectFit
    }
}

override var image: UIImage? { didSet { updateUI() }}

override func layoutSubviews() {
    super.layoutSubviews()
    updateUI()
}

注意:这是纵横比适合宽度

Swift 5.1 iOS 13

因为我的位于 collection 视图的 header 单元格中,这对我有用:

if headerCell!.imageView.frame.width > headerCell!.imageView.frame.height {
    headerCell!.imageView.contentMode = .scaleAspectFit
    //since the width > height we may fit it and we'll have bands on top/bottom
} else {
     headerCell!.imageView.contentMode = .scaleAspectFill
     //width < height we fill it until width is taken up and clipped on top/bottom
}

对于我的案例,解决方案是设置 UIImageViewcontentMode 基于图像的高度和宽度的比率是否大于 imageView 的比率。

func setupImageViewContentMode() {
    if let image = imageView.image, image.size.height / image.size.width > imageView.frame.height / imageView.frame.width {
        imageView.contentMode = .scaleAspectFit
    } else {
        imageView.contentMode = .scaleAspectFill
    }
}

此外,请注意,您必须根据当前布局进行设置,因此调用此方法,例如在 layoutSubviews() 中,在 viewDidLayoutSubviews() 中,从后端或任何您需要的地方加载图像后,它就可以完成工作。