Arseniy
Arseniy

Reputation: 487

NSString sizeWithFont:constrainedToSize:lineBreakMode: differs from actual Label height

So here how it goes: I'm implementing a UITableView (grouped style, with 1 section) with standard UITableViewCells (style - UITableViewCellStyleSubtitle) as content. My textLabel.text can be really long, that's why I set some params in TableView:cellForRowAtIndexPath:

cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont boldSystemFontOfSize:CELL_FONT_SIZE];
cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.detailTextLabel.numberOfLines = 0;
[self configureCell:cell atIndexPath:indexPath];

To resize the cell height I've implemented tableView:heightForRowAtIndexPath: as follows:

Test *test = (Test *)[self.frc objectAtIndexPath:indexPath];
NSString *cellText = test.test_name;

UIFont *cellFont = [UIFont boldSystemFontOfSize:CELL_FONT_SIZE];

CGFloat horizontalConstraint;
if (self.bagdePresent)
{
    // there will be big badge!
    horizontalConstraint = 250.0f;
} else
{
    // there will NO badge
    horizontalConstraint = 280.0f;
}

CGSize constraintSize = CGSizeMake(horizontalConstraint, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

// return label height, 20 as gap, 30 for rating image,
return labelSize.height + 20 + 30;

First I check if there will be badge image in the cell, if so, I reduce horizontal space available.

And here's the problem (finally): for some strings (some string lengths) sizeWithFont:constrainedToSize:lineBreakMode: returns value that is less than real cell's textLabel height when I set its text property to the same string. As a result some if the cells have textLabels bigger than cell's bounds. When I add\remove some words to\from the string which displayed wrong, sizeWithFont:constrainedToSize:lineBreakMode: gives exact height which is later confirmes with textLabel actual height.

I thought it might be a problem with font, but as you see the font is the same. Where to dig from here? ;)

UPD1: Here's an example of textLabel being taller than it was calculated in heightForRowAtIndexPath: tall textLabel

Normal textLabel with longer text

Upvotes: 2

Views: 1278

Answers (1)

Tobi
Tobi

Reputation: 5519

I would recommend to take advantage of sizeToFit. First you set the width of your label to your horizontalConstraint, then you call [cell.textLabel sizeToFit] (that will adjust the height of the label to fit it's content but leave the width as you set it (almost - that means it might become a little narrower):

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat horizontalConstraint;
    if (self.bagdePresent)
    {
        // there will be big badge!
        horizontalConstraint = 250.0f;
    } else
    {
        // there will NO badge
        horizontalConstraint = 280.0f;
    }

    Test *test = (Test *)[self.frc objectAtIndexPath:indexPath];
    NSString *cellText = test.test_name;

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    label.text = test.test_name;
    UIFont *cellFont = [UIFont boldSystemFontOfSize:CELL_FONT_SIZE];           
    label.lineBreakMode = UILineBreakModeWordWrap;
    label.numberOfLines = 0;
    label.font = cellFont;

    CGRect frame = label.frame;
    frame.size.width = horizontalConstraint;
    label.frame = frame;
    [label sizeToFit];

    CGSize labelSize = label.frame.size;

    // return label height, 20 as gap, 30 for rating image,
    return labelSize.height + 20 + 30;
}

Upvotes: 2

Related Questions