NetDeveloper
NetDeveloper

Reputation: 519

UITableView Row Height Based on Cell contents

I have looked at several questions asking to adjust row height based on cell content. But in my case, I have 10 labels in one cell and each label has fixed width. Labels must wrap the text if not fit to label width. So row height depends on all 10 label's text content. That means I have to calculate height of every label for given text and take maximum height amongst all labels as row height. I have to do this for all rows. This looks to me an insufficient solution. Is there any better solution?

Thanks,

Jignesh

Upvotes: 0

Views: 2913

Answers (2)

Aaron
Aaron

Reputation: 7145

The UITableView requires that you implement heightForRowAtIndexPath in order to have a custom height for a table cell. This is because UITableView calculates the total height of the table each time the data is reloaded. You could look to cache the row-height calculations as well if the data is static.

In your case I would recommend creating a data model class that represents all 10 label's worth of text and provide a helper function on that data model class that you can call in heightForRowAtIndexPath. The helper function would encapsulate the row height calculations perhaps something like this:

Let's say you have this for a data model class that represents the data in your rows:

@interface MyDataModelClass : NSObject

@property (strong, nonatomic) NSString *label1Text;
@property (strong, nonatomic) NSString *label2Text;
// ... etc

- (CGFloat)calculateLabelHeight;

@end

Then your calculateLabelHeight method might look something like this (this is just pseudo code, obviously):

- (CGFloat)calculateLabelHeight {

    CGFloat totalHeight = 0.0;

    // Loop through your label texts calculating the variable sized height for each 
    // and adding some padding in between:

   CGSize variableSize1 = [self.label1Text sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(300, 400) lineBreakMode:NSLineBreakByWordWrapping];

   CGSize variableSize2 = [self.label2Text sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(300, 400) lineBreakMode:NSLineBreakByWordWrapping];

    totalHeight = variableSize1 + padding + variableSize2 + padding; // and so on for all your labels.

    return totalHeight;
}

Then in heightForRowAtIndexPath you can do this:

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

    MyDataModelClass *modelObject = [self.data objectAtIndex:indexPath.row];

    // Assuming model object's label text properties have been set you can do this:

    return modelObject.calculateLabelHeight;
}

It just occurred to me that one label might have a long string in it causing it to wrap and possibly overlay a second label. You may also want to add a method to a UITableViewCell subclass called repositionLabels or something that does this for you after you know each label text's height.

Unfortunately, I think this is the only way to calculate height for a cell. See this S.O. post for more info:

IOS: dynamic height with a custom uitableviewcell

Upvotes: 1

Igor Nemenonok
Igor Nemenonok

Reputation: 36

You need to calculate all heights before displaying cells. After that return row height for each row using:

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

To calculate text size use:

[yourString sizeWithFont:constrainedToSize:lineBreakMode:]

Upvotes: 2

Related Questions