So I'm trying to see how I can do following ui in code by using UIStackView
:
Notice that the image can be hidden or can even have a different size. The only thing that is constant about the image is the width.
Following is the class that I came up with:
public class MenuItemTableViewCell: UITableViewCell {
//MARK: UI elements
var titleLabel = UILabel()
var detailsLabel = UILabel()
var itemImageView = UIImageView()
var mainStackView = UIStackView()
//MARK: Variables
var menuItem: MenuItem? {
didSet {
if let item = menuItem {
titleLabel.text = item.name
detailsLabel.text = item.itemDescription
if let imageURL = item.imageURL {
itemImageView.af_setImage(withURL: imageURL) { [weak self] response in
guard let imageView = self?.itemImageView else {
return
}
switch response.result {
case .success(let image):
// Instance variable:
var imageAspectRatioConstraint: NSLayoutConstraint?
// When you set the image:
imageAspectRatioConstraint?.isActive = false
imageAspectRatioConstraint = imageView.heightAnchor.constraint(
equalTo: imageView.widthAnchor,
multiplier: 100 / image.size.height)
imageAspectRatioConstraint!.isActive = true
default:
return
}
}
} else {
itemImageView.isHidden = true
}
} else {
titleLabel.text = ""
detailsLabel.text = ""
itemImageView.image = nil
}
}
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
initViews()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func initViews() {
self.accessoryType = .disclosureIndicator
self.selectionStyle = .none
setupMainStackView()
setupTitleLabel()
setupDetailLabel()
setupItemImageViewLabel()
}
//MARK: Components setup
private func setupMainStackView() {
mainStackView.alignment = .fill
mainStackView.distribution = .fillProportionally
mainStackView.spacing = 5
mainStackView.axis = .vertical
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.layoutMargins = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
mainStackView.isLayoutMarginsRelativeArrangement = true
mainStackView.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
mainStackView.distribution = .fillProportionally
self.contentView.addSubview(mainStackView)
addMainStackViewContraints()
}
//
// Title Label
//
private func setupTitleLabel() {
titleLabel.textColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
titleLabel.numberOfLines = 1
mainStackView.addArrangedSubview(titleLabel)
addTitleLabelConstraints()
}
//
// Detail Label
//
private func setupDetailLabel() {
detailsLabel.textColor = #colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)
detailsLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
detailsLabel.numberOfLines = 2
mainStackView.addArrangedSubview(detailsLabel)
addDetailsLabelContraints()
}
//
// Item Image
//
private func setupItemImageViewLabel() {
itemImageView.contentMode = .scaleAspectFit
itemImageView.clipsToBounds = true
mainStackView.addArrangedSubview(itemImageView)
addItemImageViewConstraitns()
}
//MARK: Constraints setup
private func addTitleLabelConstraints() {
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
titleLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
}
func addDetailsLabelContraints() {
detailsLabel.translatesAutoresizingMaskIntoConstraints = false
detailsLabel.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical)
detailsLabel.setContentHuggingPriority(UILayoutPriorityRequired, for: .vertical)
}
func addItemImageViewConstraitns() {
itemImageView.translatesAutoresizingMaskIntoConstraints = false
itemImageView.widthAnchor.constraint(equalTo: mainStackView.widthAnchor).isActive = true
itemImageView.leftAnchor.constraint(equalTo: mainStackView.leftAnchor).isActive = true
}
private func addMainStackViewContraints() {
mainStackView.topAnchor.constraint(equalTo: self.contentView.topAnchor).isActive = true
mainStackView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
mainStackView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor).isActive = true
mainStackView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor).isActive = true
}
}
Currently it looks like this:
and if I remove the bottom constraint from my UIStackView
, it'd be like this:
Any help on getting a better understanding on how UIStackView
works and having a auto-resize one in UITableViewCell
is highly appreciated