0
votes

I am trying to set the height of my label inside of my UITableViewCell dynamically at runtime. The height of the label is dependent on the content. I have set in my custom UITableViewCell xib file that the UILabel should have 0 lines (no bounds). Below is my code for CellForRowAtIndexPath. I've looked around and tried a few things but nothing seems to work for me.

XYZPlayerTableViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int row = indexPath.row;
    static NSString *CellIdentifier = @"PlayerCell";
    XYZPlayerTableViewCell *cell = (XYZPlayerTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    XYZPlayer *player = [self.players objectAtIndex:row];
    NSString *nameText = player.name;
    NSString *gameText = player.game;
    
    cell.nameLabel.text = nameText;
    cell.gameLabel.text = gameText;
    [cell.gameLabel sizeToFit];
    cell.gameLabel.numberOfLines = 0;
    cell.ratingImageView.image = [self imageForRating:player.rating];

    CGSize boundingRect = CGSizeMake(cell.frame.size.width, 4000);
    CGRect expectedFrame = [cell.gameLabel.text boundingRectWithSize:boundingRect options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: cell.gameLabel.font}  context:nil];
    cell.gameLabel.frame = expectedFrame;
    
    NSLog(@"gameLabel = 0x%@  gameText = %@  gameLabelHeight = %.2f", cell.gameLabel, gameText, expectedFrame.size.height);
    return cell;
}

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int row = indexPath.row;
    
    //set width depending on device orientation
    self.cellPrototype.frame = CGRectMake(self.cellPrototype.frame.origin.x, self.cellPrototype.frame.origin.y, tableView.frame.size.width, self.cellPrototype.frame.size.height);
    
    // Get variables
    XYZPlayer *player = [self.players objectAtIndex:row];
    UILabel *nameLabel = self.cellPrototype.nameLabel;
    NSString *nameText = player.name;
    UILabel *gameLabel = self.cellPrototype.gameLabel;
    NSString *gameText = player.game;
    
    // Calculate height
    CGFloat nameLabelHeight =  [self sizeOfLabel:nameLabel withText:nameText].height;
    CGFloat gameLabelHeight = [self sizeOfLabel:gameLabel withText:gameText].height;
    CGFloat padding = nameLabel.frame.origin.y;
    CGFloat combinedHeight = padding + nameLabelHeight + padding/2 + gameLabelHeight + padding;

    return combinedHeight;
}

XYZPlayerTableViewCell.m

-(void)setGameLabelHeightForString:(NSString *)string
{
    self.gameLabel.numberOfLines = 0;
    gameLabel.text = string;
    CGSize maximumLabelSize = CGSizeMake(gameLabel.frame.size.width, FLT_MAX);
    CGSize expectedLabelSize = [string sizeWithFont:self.gameLabel.font constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping]; 
    CGRect newFrame = self.gameLabel.frame;
    newFrame.size.height = expectedLabelSize.height;
    self.gameLabel.frame = newFrame;
}


-(void) layoutSubviews
{
    [self setGameLabelHeightForString:gameLabel.text];
}

The output at runtime is this:

2014-07-09 00:21:32.277 MyTestApp[24503:60b]

gameLabel = 0x< UILabel: 0x8e42800; frame = (0 0; 321.946 81.124); text = 'Tic-Tac-Toe And another l...'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = < CALayer: 0x8e360d0>>

gameText = Tic-Tac-Toe And another line and maybe some more because who know's how long this can go. I think i need just a little bit more text to make this super obvious

gameLabelHeight = 81.12

And this is what my app looks like. The gray color shows the height of my label Screen shot

Any one got any ideas of what I'm doing wrong?

6
Have you implement – tableView:heightForRowAtIndexPath: method? or set rowHeight property of UITableView .Toseef Khilji
You need to implement heightForRowAtIndexPath.Hot Licks
I've already implemented the heightForRowAtIndexPath method. And you can see from the size of my UITableViewCell that it has already grown to an appropriate heightVince613
You should set the numberOfLines of gameLabel to zero.Shiva Kumar Ganthi
Were you ever able to fix this? I'm having the exact same problem. ThanksJan

6 Answers

0
votes

You could use this to calculate height but it is not a recommended way

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

     XYZPlayerTableViewCell *cell=(XYZPlayerTableViewCell *)[self tableView:tblView cellForRowAtIndexPath:indexPath];
     return CGRectGetMaxX(cell.gameLabel.frame)+5;
}
0
votes

use one more line of code

cell.gameLabel.numberOfLines = 0;
0
votes

To resize your Label according to your content you have to make sure of 2 things

Number of lines = 0 and call sizeToFit on your label.

Not sure if you are setting the lines. Try to set the lines inside delegate only, else it seems ok

 UILabel *tempLabel = [[UILabel alloc]initWithFrmae:_textView.bounds];
 tempLabel.numberOfLines = 0; // Important to do 
 tempLabel.text = @"Your Text";
 [tempLabel sizeToFit]; // This will resize your Label and now you can use it's height to manage your textView.

This will resize the tempLabel according to it's text. Try to set the numberOfLines inside the delegate only. Also try to give the height of your cell according to your Labels by calculating them inside heightForRowAtIndexPath delegate

0
votes
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    float calulatedWidth = [self getWidthFromString:textTobePutInLabel];
    float calculatedHeight = [self getHeightFromString:textTobePutInLabel];
    cell.gameLabel.frame = CGRectMake(yourX,yourY,calulatedWidth,calculatedHeight)
    cell.gameLabel.text = gameText;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

   float height = [self getHeightFromString:textTobePutInLabel];
   return height;
}

- (float)getWidthFromString:(NSString *)strName{

    CGSize maximumSize = CGSizeMake(9999, 9999);

    CGSize size = [strName boundingRectWithSize:maximumSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont fontWithName:MAVEN_PRO size:13.0f]} context:nil].size;

    return size.width;
}

- (float)getHeightFromString:(NSString *)strName{

    CGSize maximumSize = CGSizeMake(9999, 9999);

    CGSize size = [strName boundingRectWithSize:maximumSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont fontWithName:MAVEN_PRO size:13.0f]} context:nil].size;

    return size.height;
}
0
votes

You need to do two things

  1. Override heightForRowAtIndexPath of UITableViewDelegate to return height of the cell dynamically based on the text.

  2. Override layoutSubviews of UITableViewCell (XYZPlayerTableViewCell) to recalculate and set the frame for label.

YOu can use

CGSize labelSize = [self.gameLabel.text sizeWithFont:[UIFont systemFontOfSize:11]
                                             constrainedToSize:CGSizeMake(300, NOTIFICATION_DESC_MAX_HEIGHT + 5)
                                                 lineBreakMode:NSLineBreakByWordWrapping];

for calculating best fitted height if you are setting String to label or

CGRect rect = [self.gameLabel.attributedText boundingRectWithSize:CGSizeMake(300, NOTIFICATION_DESC_MAX_HEIGHT + 5)
                                                                    options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                                                    context:nil];

if you are using AttributedString for your label

-- Vishal

0
votes

I've checked your code and I noticed one problem with the statement [gameLabel sizeToFit]; to be placed after setting the frame for the label.

i.e., after these lines

CGSize boundingRect = CGSizeMake(cell.frame.size.width, 4000);
CGRect expectedFrame = [cell.gameLabel.text boundingRectWithSize:boundingRect options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: cell.gameLabel.font}  context:nil];
cell.gameLabel.frame = expectedFrame;