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
What does your logic look like in:
- (CGSize) collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
Should be something like...
return the appropriate height
Some good examples live here what is NSLayoutConstraint "UIView-Encapsulated-Layout-Height" and how should I go about forcing it to recalculate cleanly
In general, using UIStackView in UITableViewCell is not a good idea. It may cause performance issues. But if you like you can try calling layoutIfNeeded() method of your cell when you are configuring it (especially after setting image view of the cell). Maybe it'll help.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.