I have an UITableViewCell
where I put in its contentView
labels and other things using the auto layout. I added constraints, one of them being that the contentView
has the same bounds than the UITableViewCell
.
(On the storyboard
, for convenience, I selected iphone 4-inch
as the size of the simulated metrics
.)
After adding the constraints, I call layoutIfNeeded
as I need to get the size of my cells. The constraints are indeed laid out as I can see that my contentView
is now the same size of the UITableViewCell
. The problem is that the size of the UITableViewCell
hasn't been adapted to the size of the screen yet (I guess it's done automatically later as my cells are fine). So I'm still on the size of an iphone 4 inches while I am on an iphone 4.7 inches.
Is there a way to trigger the final size of my cells like there is a way to force lay out using layoutIfNeed
?
Image view without an image selected has no intrinsic content size, hence we need to set an explicit height constraint for it. The key to achieve dynamic height table view cell is to let Auto Layout know how to calculate the height of the cell.
Auto layout is a property you can add to frames and components. It lets you create designs that grow to fill or shrink to fit, and reflow as their contents change. This is great when you need to add new layers, accommodate longer text strings, or maintain alignment as your designs evolve.
A view that presents data using rows in a single column.
When you load the cell from storyboard or nib, it has the specified size in the nib not the final one. In cellForRowAtIndexPath
add your views and constraint to the contentView
, then adjust the width doing cell.width = tableView.width
. Finally, call layoutIfNeeded
as you were doing it before.
That will cause a complete layout with the correct width of the cell.
Edit: This works because even though you are loading the nib with autolayout enabled (translatesAutoresizingMasksIntoConstraints = NO
), the first view of every nib file has always autolayout disabled (translatesAutoresizingMasksIntoConstraints = YES
).
This means that when rendering the view (so doing layoutIfNeeded
), autolayout will consider the actual frame and masks property to determine the correct size.
You don't need to call layoutIfNeeded after adding constraints.
You can subclass your cell and override - (void)layoutSubviews method to get frame changes or you can add an observer to the cell if you don't want to subclass it.
[cell addObserver:yourObserver forKeyPath:@"self.frame" options:NSKeyValueObservingOptionNew context:NULL];
and then, in the observer's class
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(object==cell && [keyPath isEqualToString:@"self.frame"]) {
//your code...
}
}
If it doesn't work, try to replace cell by cell.contentView.
Edit: If you want to create a subview by using constraints that matches the height of the cell and has a width of 100 and with is left aligned to the cell.
UIView *createdSubview = [[UIView alloc] init];
createdSubview.translatesAutoresizingMaskIntoConstraints = NO;
[cell.contentView addSubview:createdSubview];
//Left align
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[createdSubview]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];
// Fit the parent view height
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[createdSubview]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];
// Width constraint
[cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[createdSubview(==100)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(createdSubview)]];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With