Janosch Hübner
Janosch Hübner

Reputation: 1694

UITableViewCell contentView insets and Auto Layout

My problem is, that I want to inset the cell's contentView by 10 for each top, bottom, left, right. I want to use this space as a separator and disable the default table view separator. It looks like this without the insets:

without separation

Now there are two issues:

  1. Issue: Ambiguous height constraints (in the view debugger)
  2. No separator

1.

ambiguous height constraints

  1. I can change this by overriding layoutSubviews for my table view cell:

    override func layoutSubviews() {
       super.layoutSubviews()
    
       let contentViewFrame = self.contentView.frame
       let insetContentViewFrame = contentViewFrame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
       self.contentView.frame = insetContentViewFrame
       self.selectedBackgroundView?.frame = insetContentViewFrame
    }
    

However this causes issue number 3:

issue no 3

Now the description label has issues:

Here is my Table View Cell (which uses autolayout so the labels define the cell height):

class NewsTableViewCell : UITableViewCell {

public private(set) var titleLabel: UILabel!
public private(set) var descriptionLabel: UILabel!

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

    self.tintColor = UIColor.white

    self.contentView.backgroundColor = UIColor.barTintColor
    self.contentView.layer.masksToBounds = false
    self.contentView.layer.cornerRadius = 10.0

    self.backgroundColor = UIColor.clear

    let layoutGuide = self.contentView.layoutMarginsGuide

    self.titleLabel = UILabel(frame: .zero)
    self.titleLabel.numberOfLines = 0
    self.titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
    self.titleLabel.textColor = UIColor.white
    self.titleLabel.adjustsFontSizeToFitWidth = false
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
    self.titleLabel.textAlignment = .left
    self.contentView.addSubview(self.titleLabel)

    self.titleLabel.setContentCompressionResistancePriority(.required, for: .vertical)

    self.titleLabel.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
    self.titleLabel.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
    self.titleLabel.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true

    self.descriptionLabel = UILabel(frame: .zero)
    self.descriptionLabel.numberOfLines = 0
    self.descriptionLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
    self.descriptionLabel.textColor = UIColor.lightGray
    self.descriptionLabel.adjustsFontSizeToFitWidth = false
    self.descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
    self.descriptionLabel.textAlignment = .left
    self.contentView.addSubview(self.descriptionLabel)

    self.descriptionLabel.setContentCompressionResistancePriority(.required, for: .vertical)

    self.descriptionLabel.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
    self.descriptionLabel.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
    self.descriptionLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 5.0).isActive = true
    self.descriptionLabel.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

    let selectedView: UIView = UIView(frame: .zero)
    selectedView.backgroundColor = UIColor.gray
    selectedView.layer.cornerRadius = 10.0
    selectedView.layer.masksToBounds = false
    self.selectedBackgroundView = selectedView
}

That is my table view controller code:

self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 200.0
self.tableView.register(NewsTableViewCell.self, forCellReuseIdentifier: "NewsCell")
self.tableView.separatorStyle = .none

Is there any way I can both inset my contentView and have dynamically sizing labels (that define the cell height)? Thanks!

Upvotes: 2

Views: 7540

Answers (2)

Prashant Tukadiya
Prashant Tukadiya

Reputation: 16456

Your issue

1 ) You want two label to grow dynamically.
2) You want your cell resize with your content

To do this you need to give constraint at all side (left,lead, trail,bottom) otherwise Automatic dimension won't work

but auto layout engine won't allow this. because it needs some specific idea that which label will grow so it may calculate internally. and . you are getting error to change content hugging priority

Solution is also simple

Suppose from bottom you need 8px space then apply greater than equal to( >=) Relation with 8 value

and reset your content hugging priority to default they don't required now :)

enter image description here

Upvotes: 0

Shehata Gamal
Shehata Gamal

Reputation: 100533

1- Add constant paramter

 self.titleLabel.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor,constant:10).isActive = true

for leading , trailing , top and bottom

2-

lower descriptionLabel bottom constraint's priority to 999

Upvotes: 1

Related Questions