Question

How would one modify the following snippet (in a tableView:cellForRowAtIndexPath: UITableViewController method) from the "09a - PrefsTable" recipe from Chapter 6 of The iPhone Developer's Cookbook:

if (row == 1) { 
    // Create a big word-wrapped UILabel 
    cell = [tableView dequeueReusableCellWithIdentifier:@"libertyCell"]; 
    if (!cell) { 
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"libertyCell"] autorelease]; 
        [cell addSubview:[[UILabel alloc] initWithFrame:CGRectMake(20.0f, 10.0f, 280.0f, 330.0f)]]; 
    } 
    UILabel *sv = [[cell subviews] lastObject]; 
    sv.text =  @"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation."; 
    sv.textAlignment = UITextAlignmentCenter; 
    sv.lineBreakMode = UILineBreakModeWordWrap; 
    sv.numberOfLines = 9999; 
    return cell; 
} 

...to size the "sv" UILabel subview and the "cell" UITableViewCell to be sized just big enough to fit the text (and work with more or less text, and other types of text alignment)?  I looked at the UILabel textRectForBounds:limitedToNumberOfLines: method, but the documentation states that it should not be called directly (and should only be overridden).  I experimented with the UIView sizeToFit method, without success.

Update: I asked a new question about my problem with the NSString -sizeWithFont:forWidth:lineBreakMode: method.

Was it helpful?

Solution

I had to do this enough that I extended UILabel to do it for me:

@interface UILabel (BPExtensions)
- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth;
@end

@implementation UILabel (BPExtensions)


- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth
{
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, fixedWidth, 0);
    self.lineBreakMode = NSLineBreakByWordWrapping;
    self.numberOfLines = 0;
    [self sizeToFit];
}
@end

then to have a label to have a variable multiline height but a fixed width just:

[myLabel sizeToFitFixedWidth:kSomeFixedWidth];

OTHER TIPS

You should use NSString's -sizeWithFont:forWidth:lineBreakMode: method to retrieve the associated sizing metrics for your label.

Also, change the numberOfLines property to 0 if you're going to use that code.

NSString's -sizeWithFont:forWidth:lineBreakMode: does not actually perform the word wrap. Instead, use -sizeWithFont:constrainedToSize:lineBreakMode: to get an accurate width AND height value for the string.

Try this:

sv.text =  @"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation."; 
sv.textAlignment = UITextAlignmentCenter; 
sv.lineBreakMode = UILineBreakModeWordWrap; 
sv.numberOfLines = 0;
[sv sizeToFit]; 

Also, you will need to implement the UITableViewDelegate method:

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

And have it return a total cell height adjusted for the resized text field.

One other note - Size to Fit should actually work, if you have number of lines set to 0 as previously mentioned. It would give you back a size with the height increased to accomidate the word-wrapped text set in the label and the width set to whatever the original label width had.

That will not help you though as you need to get the size in heightForRow before the cell is obtained, so you are better off calculating the height needed (and very probably caching that calculation so as not to slow down table rendering)

Here's a bit of code i use:

CGSize textSize = [myLabel.text sizeWithFont:myLabel.font];

I had similar problem, I had a UITableViewCell that was designed in StoryBoards as a static cell. I used [super tableView:cellForRowAtIndexPath:] to get it. So I wanted to resize the UILabel "detailTextLabel" so it fits the text I set to it. The style was "Right Detail".

I just set the text in my tableView:cellForRowAtIndexPath:. And than in tableView:heightForRowAtIndexPath: I returned

UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
return cell.detailTextLabel.frame.size.height

I had long string. And finally had a wide Cell with 4 lines of text in label.

I had similar problem. I solved this.

In cellForRowAtIndexPath method set font size to whatever you want.

cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;    
[cell.textLabel setFont:[UIFont systemFontOfSize:14.0]];
[cell.textLabel sizeToFit];

And in heightForRowAtIndexPath method increase font size.

    CGFloat height;

    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    NSString *text = cell.detailTextLabel.text;
    CGSize constraint = CGSizeMake(320, 20000.0f);
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:20.0]     constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
    CGFloat calHeight = MAX(size.height, 44.0f);
    height =  calHeight + (CELL_CONTENT_MARGIN * 2);

    return height;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top