Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know the width of an UITableViewCell when using auto layout?

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?

like image 870
Nico Avatar asked Jul 07 '15 09:07

Nico


People also ask

How do you create a dynamic height table in a cell?

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.

Why do we use Auto Layout?

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.

What is Uitableview in Swift?

A view that presents data using rows in a single column.


2 Answers

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.

like image 156
Pauls Avatar answered Sep 28 '22 01:09

Pauls


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)]];
like image 45
Jaeger Avatar answered Sep 28 '22 02:09

Jaeger