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

自闭症网瘾萝莉.ら 提交于 2019-12-22 01:46:02

问题


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?


回答1:


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.




回答2:


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



回答3:


For me setting content hugging priority and content compression resistance priority lower to one of the element worked just as expected.



来源:https://stackoverflow.com/questions/26055887/ios-7-8-uitableview-cell-two-uilabels-with-dynamic-height-with-auto-layout-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!