NSLayoutAnchor & UITableViewCell
Requirement
Task was to create a tableview, with such cells, based on a sketch:
I decided to use a custom UITableViewCell. I also created a xib file, to lay out the UI part:
I wanted to try out NSLayoutAnchor’s, as I’ve never used them before. And I implemented them in code.
Solution
First set for all of the properties - translatesAutoresizingMaskIntoConstraints = false
backgroundImageView.translatesAutoresizingMaskIntoConstraints = false
iconImageView.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
addressesLabel.translatesAutoresizingMaskIntoConstraints = false
priceLabel.translatesAutoresizingMaskIntoConstraints = false
And then set up anchors for all the outlets:
1.) Background imageView
Then we set up background image view (shadowy frame). It depends on the type of graphic you have (I had a lot of shadows), So I simply set it to be offset from top/bottom/left/right borders of contentView. Right and bottom is negative, so they would be inset.
backgroundImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15).isActive = true
backgroundImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 15).isActive = true
backgroundImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -10).isActive = true
backgroundImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true
2.) Icon imageView
Icon is always in the top left corner, and we also know it’s size.
iconImageView.leftAnchor.constraint(equalTo: backgroundImageView.leftAnchor, constant: 10).isActive = true
iconImageView.topAnchor.constraint(equalTo: backgroundImageView.topAnchor, constant: 10).isActive = true
iconImageView.widthAnchor.constraint(equalToConstant: 33).isActive = true
iconImageView.heightAnchor.constraint(equalToConstant: 33).isActive = true
3.) Title label
Title label is also always at the top left corner, next to icon. But width and height will be auto-calculated.
titleLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 10).isActive = true
titleLabel.topAnchor.constraint(equalTo: backgroundImageView.topAnchor, constant: 6).isActive = true
4.) Address label
Addresses label is always under the title label, and cell should end at the bottom of address label
addressesLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 10).isActive = true
addressesLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 3).isActive = true
addressesLabel.bottomAnchor.constraint(equalTo: backgroundImageView.bottomAnchor, constant: -12).isActive = true
5.) Price label
Price label should begin where ends titleLabel, or addressLabel This will at the very least - constraint the titleLabel / addressLabel widths
priceLabel.leftAnchor.constraint(greaterThanOrEqualTo: titleLabel.rightAnchor, constant: 6).isActive = true
priceLabel.leftAnchor.constraint(greaterThanOrEqualTo: addressesLabel.rightAnchor, constant: 6).isActive = true
For priceLabel we set the right side, top side and bottom (as it is centered in right side)
priceLabel.rightAnchor.constraint(equalTo: backgroundImageView.rightAnchor, constant: -18).isActive = true
priceLabel.topAnchor.constraint(equalTo: backgroundImageView.topAnchor, constant: 6).isActive = true
priceLabel.bottomAnchor.constraint(equalTo: backgroundImageView.bottomAnchor, constant: -12).isActive = true
We also need to provide some minimum width for the price label, so that it would not shrink smaller because of title or address.
priceLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 80).isActive = true
Result
And the final result:
P.S.
At first, I used a very large exported image for backgroundImageView. And because image by default was quite large, it then forced cell to be larger:
And the solution was simply to export a minimal size image for backgroundImageView (which then could be sliced):