Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 7/8 UITableView Cell: Two UILabels with dynamic height with auto layout for variable row height

So I am able to set up dynamic height sizing with auto layout when I have only one label that changes the height based on the length of the string. My problem is that if I add another UILabel that should do the same, things don't work out.

I am setting both the Content Hugging priority and the Compression Resistance to 1000 for both == I get warnings of ambiguity

If I set the Content Hugging (Vertical) for the second UILabel to 999 or 250 then it works great but only if the second label has 2 or more line. If the second label is blank or has only one line, the heightForRowAtIndexPath systemLayoutSizeFittingSize:UILayoutFittingCompressedSize height returns large values, and the cells have large blank spaces.

I also played around with the Intrinsic Size: Default or Placeholder(with couple of heights and widths) but it does not help either.

Anyone any suggestions what can be done?

like image 994
Zsolt Avatar asked Sep 26 '14 09:09

Zsolt


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.

What is Uitableview in Swift?

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


2 Answers

I got it working finally. The solution was for me to explicitly set the Preferred Width to the current frame width. So basically checking the Explicit check mark in the Label > Preferred Width in the Size Inspector.

ref: http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout download the sample code and see the storyboard setup.

like image 137
Zsolt Avatar answered Oct 20 '22 18:10

Zsolt


For me it took a combination of several things.

  • Besides setting the content hugging and resistance correct
  • I had to make a subclass of UILabel to handle the preferredMaxLayoutWidth of the label
  • and correct a bug in the intrinsicContentSize as well

The UILabel subclass ended up looking like this:

@implementation LabelDynamicHeight

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.preferredMaxLayoutWidth = self.frame.size.width;

    [super layoutSubviews];
}

- (void)setBounds:(CGRect)bounds
{
    [super setBounds:bounds];

    if (self.numberOfLines == 0)
    {
        CGFloat boundsWidth = CGRectGetWidth(bounds);
        if (self.preferredMaxLayoutWidth != boundsWidth)
        {
            self.preferredMaxLayoutWidth = boundsWidth;
            [self setNeedsUpdateConstraints];
        }
    }
}

- (CGSize)intrinsicContentSize
{
    CGSize size = [super intrinsicContentSize];

    if (self.numberOfLines == 0)
    {
        // There's a bug where intrinsic content size may be 1 point too short
        size.height += 1;
    }

    return size;
}

@end

Besides this calling layoutIfNeeded on the cell before getting the height in tableView heightForRowAtIndexPath: made the constraints to be ready before using the systemLayoutSizeFittingSize: method on the contentView. Looking like this:

- (CGFloat)tableView:( UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = ...;
    CGFloat height = cell.frame.size.height;
    if (cell.dynamicHeight)
    {
        // https://stackoverflow.com/a/26351692/1840269
        [cell layoutIfNeeded];
        height = cell.frame.size.height;

        CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
        if (size.height > height)
            height = size.height;
    }
    return height;
}

References:

  • Preferred for content hugging and resistance: https://stackoverflow.com/a/16281229/1840269
  • Description of the preferredMaxLayoutWidth manipulation: https://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/
  • Inspiration for the UILabel subclass with the intrinsicContentSize fix: https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8/issues/7
like image 21
micmdk Avatar answered Oct 20 '22 16:10

micmdk