iOS - Autolayout and Resizing UILabel (iOS/Swift)
Last week I had weird issue while applying autolayout rules to UITableViewCell. TableViewCell has two components attached to it.
- An
UIImageView - Two variable length
UILabels stacked vertically on the top of each other
And I wanted tableView cells to look like this,

Nice, isn't it? Let's look at the way vertical constraints are arranged in the tableViewCell.
-
A top of
UIImageViewis attached to top ofcontentViewwith fixed height -
Main label and Sub label are stacked vertically with variable height which is adjusted to the text content
-
Top of Main label is attached to top of
contentViewand bottom of Sub label is attached to bottom ofcontentViewso that cell is stretched according to size of these twoUILabels
Having looked at primary setup, let's look at the problem with this approach.
- Attaching top of Main label with top of
contentViewand bottom of Sub label with bottom ofcontentView
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[imageV(74)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[mainLabel]-[subLabel]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
- This approach will work well when content of labels is well enough to stretch the
UITableViewCellto vertically accommodate imageView. But, if content of labels is not enough, cell with shrink so as to eclipse the remaining height of imageView as follows

Let's look at other solution,
- Attaching the top and bottom of
UIImageViewto the top and bottom ofcontentViewrespectively.
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[imageV(74)]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[mainLabel]-[subLabel]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
- This approach will not work either from following screenshot since bottom of imageView is attached to bottom of
contentView, we will no longer have variable height cell since height of imageView is always the same which will cause visual issue forUILabelwhich is expected to have variable height

- Attaching both labels and imageView to the top and bottom of
contentViewwill not work either since their respective bottoms withcontentViewwill cause an autolayout ambiguity for variable length labels
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[imageV(74)]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[mainLabel]-[subLabel]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
Solving autolayout issue
Now, let's look at it how it can be solved to accommodate fixed height UIImageView as well as variable height UILabels.
We already know the fixed height of UIImageView. Thus we can adjust total height of UILabels to be minimum of height of UIImageView so that even if there is no enough content to UILabel, it will stretch to at least minimum height to accommodate the imageView height.
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[imageV(74)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[mainLabel(>=32)]-[subLabel(>=32)]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
-
Total height of
UIImageViewis 74 plus top vertical padding of 5 pixels which is fixed -
Total minimum height of two
UILabels stacked vertically is 64 plus 10 considering top vertical padding which is 74. This meansUILabelside maintains at least a height of 74 pixels to accommodate bothUILabels andUIImageView
The result is as follows,
- Not enough content on labels (Main and Sub label)

- Too much content on labels (Main and Sub label)

Hope this will help someone someday. Let me know if you have come up with any other solutions to tackle the similar problem. Autolayout is fun, not because it's confusing, but it instills an inspiration to look for innovative solutions. Obviously, the beauty of it is there is no single solution, but there could be many. That's why I am looking forward to hear from you soon

