使用高度/宽度值在 UITableViewCell 中设置 UIImageView 的高度

Set height for UIImageView in UITableViewCell using height / width values

我需要在 UITableViewCell 内渲染图像。

API returns 图像的原始高度和宽度,所以我相信我应该可以计算出比例。但是我不确定如何使用自动布局来布置它。

final class ContentArticleImage: UITableViewCell {

  var ratio: CGFloat? { // 1000 / 600 (width / height)
    didSet {
      guard let ratio = ratio else { return }
      contentImageView.heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1 / ratio).isActive = true
    }
  }

  private lazy var contentImageView = configure(UIImageView(frame: .zero), using: {
    [=10=].translatesAutoresizingMaskIntoConstraints = false
    [=10=].backgroundColor = .darkGray
    [=10=].contentMode = .scaleAspectFit
  })

  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    configureUI()
  }

  required init?(coder: NSCoder) {
    return nil
  }
}
private extension ContentArticleImage {
  func configureUI() {

    addSubview(contentImageView)
    NSLayoutConstraint.activate([
      contentImageView.topAnchor.constraint(equalTo: topAnchor, constant: 12),
      contentImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
      contentImageView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12),
      contentImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12)
    ])

  }
}

我试过类似上面的方法,但我会出现自动布局错误

(
    "<NSLayoutConstraint:0x600002885b30 V:|-(12)-[UIImageView:0x7ffe3551e170]   (active, names: '|':OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage' )>",
    "<NSLayoutConstraint:0x600002885c70 UIImageView:0x7ffe3551e170.bottom == OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage'.bottom - 12   (active)>",
    "<NSLayoutConstraint:0x600002885ea0 UIImageView:0x7ffe3551e170.height == 0.548298*OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage'.width   (active)>",
    "<NSLayoutConstraint:0x6000028860d0 'UIView-Encapsulated-Layout-Height' OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage'.height == 251   (active)>",
    "<NSLayoutConstraint:0x600002886080 'UIView-Encapsulated-Layout-Width' OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage'.width == 414   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600002885c70 UIImageView:0x7ffe3551e170.bottom == OneHubApp.ContentArticleImage:0x7ffe3551ddc0'ContentArticleImage'.bottom - 12   (active)>

使用原始高度/宽度我应该如何计算单元格中图像的高度?

编辑 我的单元格是使用以下方法呈现的:

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CONTENT_CELL", for: indexPath) as! ContentArticleImage
    cell.ratio = asset.width / asset.height
    cell.selectionStyle = .none
    return cell
  }

您需要做的是在每次重复使用单元格时停用高度限制。此外,您需要将高度约束设置为 contentImageView 宽度约束的倍数,而不是单元格的宽度约束。所以你的代码应该是这样的:

final class ContentArticleImage: UITableViewCell {

    var heightConstraint: NSLayoutConstraint?

    var ratio: CGFloat? { // 1000 / 600 (width / height)
        didSet {
            guard let ratio = ratio else { return }
            heightConstraint?.isActive = false
            heightConstraint = contentImageView.heightAnchor.constraint(equalTo: contentImageView.widthAnchor, multiplier: 1 / ratio)
            heightConstraint?.isActive = true
            heightConstraint?.priority = .defaultHigh
        }
    }

    lazy var contentImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.backgroundColor = .darkGray
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        configureUI()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configureUI()
    }
}

请注意,我将 priority 设置为 .defaultHight 只是为了消除控制台中的布局警告。