I need to render an image within a UITableViewCell
.
The API returns the original height and width of the image, so I believe I should be able to calculate the ratio. However I am unsure how to lay this out using autolayout.
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: {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.backgroundColor = .darkGray
$0.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)
])
}
}
I tried something like the above, but I can an autolayout error
(
"<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)>
Using the original height / width how should I calculate the height of an image in my cell?
EDIT My cell is rendered using the following method:
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
}
What you need to do is deactivate your height constraint each time the cell is reused. Also, you need to set the height constraint equal to a multiple of the contentImageView
width constraint, not the cell's width constraint. So your code should look something like this:
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()
}
}
Note that I'm setting the priority
to .defaultHight
just to silence a layout warning in the console.