简体   繁体   English

UIImageView 保持纵横比,但适合宽度

[英]UIImageView keep aspect ratio, but fit to width

I have a UIImageView with a fixed width and height.我有一个固定宽度和高度的 UIImageView。 I don't want to change the frame of the UIImageView.我不想改变 UIImageView 的框架。 I want to have it hold an image where I keep the aspect ratio and I fit the width and let the image be either too tall, or too short for the UIImageView's frame.我想让它保存一个图像,在那里我保持纵横比,我适合宽度,让图像对于 UIImageView 的框架来说要么太高,要么太短。 Like this:像这样:

UIImageView 框架

The red is the UIImageView's frame.红色是 UIImageView 的框架。 The gray is the actual image as it's displayed.灰色是显示的实际图像。

I think the best way to do it is to play with the mode of your imageView (Aspect Fill, Aspect Width, etc) and this is based on the ratio between the width and height of the image我认为最好的方法是使用 imageView 的模式(纵横比填充、纵横宽等),这是基于图像的宽度和高度之间的比率

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 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 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.内容的某些部分可能会被裁剪以填充视图的边界。

I haven't tested it but off the top of my head this seems right我还没有测试过,但我觉得这似乎是对的

I think you need to compare the image aspect ratio to the aspect ratio of the UIImageView itself:我认为您需要将图像纵横比与 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()
}

Note: this is aspect fit width注意:这是方面适合宽度

Swift 5.1 iOS 13斯威夫特 5.1 iOS 13

Because mine was on the header cell on a collection view this is what worked for me:因为我的位于集合视图的标题单元格上,所以这对我有用:

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
}

For my case solution was to set UIImageView 's contentMode based on if ratio of image's height and width is bigger than of imageView 's.对于我的情况下的解决办法是设置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
    }
}

Also, note that you have to setup this according to current layout, so calling this method eg in layoutSubviews() , in viewDidLayoutSubviews() , after image is loaded from backend or wherever you need it does the job.另外,请注意,您必须根据当前布局进行设置,因此在从后端或任何您需要的地方加载图像后,例如在layoutSubviews()viewDidLayoutSubviews()调用此方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM