I have a UITableViewCell subclass which contains a multiline label, and I would like the cell to size itself dynamically based on the content of that label. I\'m aware that
Are you sure you have -translatesAutoresizingMaskIntoConstraints set to NO on the cell? If you don't, the system generates constraints based on the autoresizing mask, which was the previous way of doing layout on iOS, and should be disabled when using Auto Layout.
In order to implement automatic row heights for table view cells, you need to do the following:
Implement Auto Layout constraints within the cell's contentView that allow the view to express its preferred height. Be sure to set UILabel
s to word wrap over multiple lines.
Be sure you've defined an axial chain of constraints in both dimensions, that is, constraints that collectively bind all the way from one edge of the view to the other. Perhaps the easiest way to be sure these constraints are correct is to implement your custom content as a plain old UIView
(which is easy to test), and then use constraints so that the UITableViewCell.contentView
hugs that view. (I use this gist to automate building the "view-wrapping cell".)
Set tableView.rowHeight = UITableViewAutomaticDimension
Set tableView.estimatedRowHeight = 400
or some other reasonably generous value, in order to workaround some UIKit bugs when the estimate is too low.
I have spent a puzzling amount of time working with this feature. This github repo shows seven complete examples of self-sizing table view cells containing a single label of wrapping text -- programmatic, nib-based, storyboard-based, etc..
Finally, do not worry too much if you see warnings about unsatisfiable constraints mentioning "UIView-Encapsulated-Layout-Height" or similar at the first time the table view loads. This is an artefact of UITableView
's initial process for creating a cell, determining what its size should be based on Auto Layout Constraints, and keeping the UITableViewCell
tightly wrapping its contentView
. The repo I mentioned above has more extensive discussion and code for exploring this somewhat awkward corner of the API.
You should only worry about constraint-violation warnings if they persist even after the cell has loaded and has scrolled a bit, or if you are seeing incorrect layouts initially. In this case, again, the first step should always be to ensure your constraints are correct by developing them and testing them in isolation if possible, in a plain UIView
.
I just came across this issue.
From numerous other Stackoverflow post they recommend:
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
That didn't work for me at first. I found that I also need to do:
self.frame = CGRectMake(0, 0, self.frame.size.width, 50);
My custom cell's init method looks like his:
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
[self initViews];
[self initConstraints];
}
return self;
}
I put the code in my "initViews" method:
-(void)initViews
{
...
// fixes an iOS 8 issue with UIViewEncapsulated height 44 bug
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.frame = CGRectMake(0, 0, self.frame.size.width, 50);
}
The problem went away and my cell looks correct too.
Does this work for you?