【问题标题】:UIImageView keep aspect ratio, but fit to widthUIImageView 保持纵横比,但适合宽度
【发布时间】:2021-08-24 16:07:19
【问题描述】:

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

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

【问题讨论】:

    标签: ios swift uiimageview uiimage aspect-ratio


    【解决方案1】:

    我认为最好的方法是使用 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

    通过保持 纵横比。视图边界的任何剩余区域都是透明的。

    UIViewContentModeScaleAspectFill

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

    我还没有测试过,但我认为这似乎是正确的

    【讨论】:

    • 太棒了,我会搞砸这个。好主意。
    • 我正在使用 MPMediaItemArtwork,该怎么做?
    • 这个解决方案不考虑视图的形状,只考虑图像的形状。此解决方案仅在视图为方形时才有效。对于宽幅图像,如果视图又宽又窄,则当它应该填充时,它会适应图像。
    【解决方案2】:

    我认为您需要将图像纵横比与 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()
    }
    

    注意:这是宽高比匹配宽度

    【讨论】:

    • 这个可以用来设置图片的纵横比为16:9吗?如果是这样,最好的方法是这样做?
    • 问题是关于保持图像的原始纵横比,但让图像显示在可能与图像不同纵横比的视图中。如果要强制图像的纵横比,可以使用约束。例如,在界面生成器中,您可以设置 UIImageView 的纵横比。这是你要问的吗?
    【解决方案3】:

    Swift 5.1 iOS 13

    因为我在集合视图的标题单元格上,所以这对我有用:

    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
    }
    

    【讨论】:

      【解决方案4】:

      对于我的情况,解决方案是根据图像的高宽比是否大于 imageView 的比率来设置 UIImageViewcontentMode

      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() 中,从后端或任何您需要的地方加载图像后。

      【讨论】:

        猜你喜欢
        • 2018-08-09
        • 1970-01-01
        • 2016-04-01
        • 2018-06-21
        • 1970-01-01
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 2016-05-18
        相关资源
        最近更新 更多