2
votes

I'm implementing my tableview cells using AutoLayout to show an image and 2 labels, using Dynamic Type for adaptive font size.

I implemented estimatedHeightForRowAtIndexPath, which makes perfect sense and is easy to use.

I don't use interface builder for the cells. Instead I use Masonry, which shouldn't make any difference.

I'm currently struggling with calculating the actual cell height. Calculating it manually is a pain and difficult to maintain when updating the auto layout code.

I found this StackOverFlow answer: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights This solution should also take care of the different font sizes, but doesn't work for me.

When I have the AutoLayout system like that: UILabel to top contentView with padding, another UILabel to bottom of contentView with padding, it should automatically calculate the cell height.

But instead, it results in the following AutoLayout conflict:

UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<MASLayoutConstraint:0xc506be0 UIImageView:0xc5070a0.height == 150>",
    "<MASLayoutConstraint:0xc506d90 UIImageView:0xc5070a0.top == UITableViewCellContentView:0xc5076e0.top + 10>",
    "<MASLayoutConstraint:0xc506990 UILabel:0xc507450.top == UIImageView:0xc5070a0.bottom + 10>",
    "<MASLayoutConstraint:0xc506630 UILabel:0xc507260.top == UILabel:0xc507450.bottom>",
    "<MASLayoutConstraint:0xc506530 UILabel:0xc507260.bottom == UITableViewCellContentView:0xc5076e0.bottom>",
    "<NSAutoresizingMaskLayoutConstraint:0xc3d05a0 UITableViewCellContentView:0xc5076e0.height == 44>"
)

I use the following AutoLayout code:

[self.subtitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.titleLabel.mas_bottom);
            make.right.equalTo(self.contentView.mas_right).with.offset(-GCBaconCellRowPadding);
            make.left.equalTo(self.contentView.mas_left).with.offset(GCBaconCellRowPadding);
            make.bottom.equalTo(self.contentView.mas_bottom);
        }];

The last line should indicate that the height of the cell extends itself.

Looking at the output of the AutoLayout conflict, it looks like it wants to set the height automatically to 44.0, which is the default value.

Edit: Setting the contentView's translatesAutoresizingMaskIntoConstraints to NO

self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

when creating the cell fixes the collision, but results in a row height of zero.

1
Did you take a look at the sample project on GitHub which effectively does what you're trying to do? github.com/caoimghgin/TableViewCellWithAutoLayoutsmileyborg

1 Answers

5
votes

I ended up using the following code:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static GCBaconCell *offscreenCell;

    if (!offscreenCell)
    {
        offscreenCell = [[GCBaconCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                    reuseIdentifier:@"nothing"];
    }


    // configure offscreenCell ...

    [offscreenCell.contentView setNeedsLayout];
    [offscreenCell.contentView layoutIfNeeded];

    CGSize maximumSize = CGSizeMake(320.0, UILayoutFittingCompressedSize.height);
    CGFloat height = [offscreenCell.contentView systemLayoutSizeFittingSize:maximumSize].height;

    return height;
}

in the controller.

In the cell view make sure to use the following line

self.contentView.translatesAutoresizingMaskIntoConstraints = NO;