My understanding of autolayout is that it takes the size of superview and base on constrains and intrinsic sizes it calculates positions of subviews.
Is there a way to reverse this process? I want to resize superview on the base of constrains and intrinsic sizes. What is the simplest way of achieving this?
I have view designed in Xcode which I use as a header for UITableView
. This view includes a label and a button. Size of the label differs depending on data. Depending on constrains the label successfully pushes the button down or if there is a constrain between the button and bottom of superview the label is compressed.
I have found a few similar questions but they don’t have good and easy answers.
Best Answer
The correct API to use is
UIView systemLayoutSizeFittingSize:
, passing eitherUILayoutFittingCompressedSize
orUILayoutFittingExpandedSize
.For a normal
UIView
using autolayout this should just work as long as your constraints are correct. If you want to use it on aUITableViewCell
(to determine row height for example) then you should call it against your cellcontentView
and grab the height.Further considerations exist if you have one or more UILabel's in your view that are multiline. For these it is imperitive that the
preferredMaxLayoutWidth
property be set correctly such that the label provides a correctintrinsicContentSize
, which will be used insystemLayoutSizeFittingSize's
calculation.EDIT: by request, adding example of height calculation for a table view cell
Using autolayout for table-cell height calculation isn't super efficient but it sure is convenient, especially if you have a cell that has a complex layout.
As I said above, if you're using a multiline
UILabel
it's imperative to sync thepreferredMaxLayoutWidth
to the label width. I use a customUILabel
subclass to do this:Here's a contrived UITableViewController subclass demonstrating heightForRowAtIndexPath:
A simple custom cell:
And, here's a picture of the constraints defined in the Storyboard. Note that there are no height/width constraints on the label - those are inferred from the label's
intrinsicContentSize
: