views:

14985

answers:

4

This is on iPhone 0S 2.0. Answers for 2.1 are fine too, though I am unaware of any differences regarding tables.

It feels like it should be possible to get text to wrap without creating a custom cell, since a UITableViewCell contains a UILabel by default. I know I can make it work if I create a custom cell, but that's not what I'm trying to achieve - I want to understand why my current approach doesn't work.

I've figured out that the label is created on demand (since the cell supports text and image access, so it doesn't create the data view until necessary), so if I do something like this:

cell.text = @""; // create the label
UILabel* label = (UILabel*)[[cell.contentView subviews] objectAtIndex:0];

then I get a valid label, but setting numberOfLines on that (and lineBreakMode) doesn't work - I still get single line text. There is plenty of height in the UILabel for the text to display - I'm just returning a large value for the height in heightForRowAtIndexPath.

A: 

I don't think you can manipulate a base UITableViewCell's private UILabel to do this. You could add a new UILabel to the cell yourself and use numberOfLines with sizeToFit to size it appropriately. Something like:

UILabel* label = [[UILabel alloc] initWithFrame:cell.frame];
label.numberOfLines = <...an appriate number of lines...>
label.text = <...your text...>
[label sizeToFit];
[cell addSubview:label];
[label release];
drewh
A: 

Add your own UILabel as a subview of the cell.contentView view.

Kendall Helmstetter Gelner
Doesn't answer the question! Does answer the title of the question though, which I have now edited.
Airsource Ltd
+34  A: 

Here is a simpler way, and it works for me:

Inside your cellForRowAtIndexPath: function. The first time you create your cell:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}

You'll notice that I set the number of lines for the label to 0. This lets it use as many lines as it needs.

The next part is to specify how large your UITableViewCell will be, so do that in your heightForRowAtIndexPath function:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = @"Go get some text for your cell.";
    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];
    CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + 20;
}

I added 20 to my returned cell height because I like a little buffer around my text.

Tim Rupe
You do not need to set your cell.textLabel.numberOfLines to some arbitrarily high number. Setting it to 0 means "as many lines as it takes to display."
mmc
Thanks, I'll edit my post tonight after I get a chance to verify it in my own project.
Tim Rupe
Setting number of lines to 0 works fine (as many lines as it takes to display)
Prakash
Thanks. I made the correction.
Tim Rupe
when I set the numberOfLines to 0, I always have a blank line at the end. Any ideas how I can get rid of that?
david
David, You probably have a newline at the end of your string. That's the only cause that comes to mind.
Tim Rupe
This works beautifully - thank you! Because some of my rows aren't "multiline" I selectively calculate the row height (and set numberOfLines and lineBreakMode as needed) ... else I just return tableView.rowHeight as a default. Tip for those trying this out: Be sure you do NOT reference your table view cell within tableView:heightForRowForIndexPath:. As handy as that would be (to get at the font for a given cell, for instance), this will cause an infinite loop, "and your debugger will be sad."
Joe D'Andrea
This works really well for me up to a point. I can only get three lines after that my text is truncated. Any idea what would cause this? I'm using the same code above with the exception of using the detailTextLabel instead of the textLabel
cagreen
@cagreen - This probably doesn't work for detailTextLabel because of subview layouts being overridden. If you really want to continue in the same direction, making a custom cell and manually managing the layoutSubviews is probably your best bet.
Tim Rupe
cagreen: Turns out I can replicate this, but *only* if I use iPhone OS 3.0 in the simulator. When I use 3.1+, the detailTextLabel's resizing matches that of sizeWithFont just fine. So Tim's method works really well - just for 3.1+ (likely due to a bug/misfeature in the 3.0 default cell rendering). For the record, I'm using a vertical top/bottom margin of 12 (each), a detail text label size of (188.0, CGFLOAT_MAX), and a boldSystemFontOfSize 15.
Joe D'Andrea
What would my cellFont be if my cells have a variety of fonts and sizes? - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *cellText = @"Go get some text for your cell."; UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0]; }
Patricia
@Patricia: That gets a bit more complicated, but essentially you'll need to track what font and size each cell has in an array or table that is indexed by the cell number. When you enter this function, look up the information you need, and apply it to get the cell size you need.
Tim Rupe
+1  A: 

I think this is a better and shorter solution. Just format the UILabel (textLabel) of the cell to auto calculate for the height by specifying sizeToFit and everything should be fine.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    cell.textLabel.text = @"Whatever text you want to put here is ok";
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    [cell.textLabel sizeToFit];

    return cell;
}
dukz
Does not work at all, cell height will not be adjusted.
Till