views:

2525

answers:

3

When writing a customized subclass of UITableViewCell, I find that the results work well for the rectangular cells of a plain-styled UITableView, but do not work at all for the rounded cells in a grouped-styled table.

Is there a way to reliably subclass UITableViewCell to draw cells which work for grouped-style tables? (Without using Interface Builder.)

A: 

What problem are you having? In drawRect you are given a rect, and know your total size - just conform to that space. If you are using layoutSubviews, same thing.

Kendall Helmstetter Gelner
The problem is UITableView in grouped mode cuts off parts of the cells (the sides, to reveal the background and it also rounds the corners of the top and bottom cells of a section).
jbrennan
Yep, that's the problem.
Alex Reynolds
After some further tests, you're right that the table view cells do not get passed in the correct size in drawRect. An alternate approach is to set a custom backgroundView for a standard UITableViewCell, and do all your drawing there. You get a cell the right width but you have to draw the rounded top and bottom corners correctly yourself.
Kendall Helmstetter Gelner
+2  A: 

I've noticed this problem as well. My workaround has been to just make my table cells smaller (300 width instead of 320). It's not a great solution, but it works well.

I don't believe you can get rid of the table view insets on an individual basis when in "grouped" mode. I could be wrong though!

Kevin Elliott
+6  A: 

I used to have lots of problems with UITableViewCell subclasses, but then I just stopped subclassing. Adding subviews to the contentView property of a UITableViewCell seems to accomplish the same thing in any instance that I've run across, so I just do that inside my UITableViewController.

Here's an example that has a title and value:

- (UITableViewCell *)tableView:(UITableView*)tableView 
      cellForRowAtIndexPath: (NSIndexPath*)indexPath 
{    
    static NSString* CellIdentifier = @"AccountDetailsCell";
    UILabel* mainLabel = nil;
    UILabel* valueLabel = nil;
    const CGFloat kAccountDetailFontSize = 14.0;

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
    if ( cell == nil ) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault 
               reuseIdentifier: CellIdentifier] autorelease];
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
     cell.selectionStyle = UITableViewCellSelectionStyleNone;

     mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake( 10.0, 0.0, 150.0, 44.0 )] autorelease];
        mainLabel.tag = MAINLABEL_TAG;
        mainLabel.font = [UIFont boldSystemFontOfSize: kAccountDetailFontSize];
        mainLabel.textAlignment = UITextAlignmentLeft;
        mainLabel.textColor = [UIColor darkGrayColor];
        mainLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
     mainLabel.backgroundColor = [UIColor clearColor];
        [cell.contentView addSubview: mainLabel];

     valueLabel = [[[UILabel alloc] initWithFrame: CGRectMake( 150.0, 0.0, 150.0, 44.0 )] autorelease];
        valueLabel.tag = VALUELABEL_TAG;
        valueLabel.font = [UIFont boldSystemFontOfSize: kAccountDetailFontSize];
        valueLabel.textAlignment = UITextAlignmentRight;
        valueLabel.textColor = [UIColor darkTextColor];
        valueLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
     valueLabel.backgroundColor = [UIColor clearColor];
        [cell.contentView addSubview: valueLabel];
    }
    else
    {
     mainLabel = (UILabel*)[cell.contentView viewWithTag: MAINLABEL_TAG];
     valueLabel = (UILabel*)[cell.contentView viewWithTag: VALUELABEL_TAG];
    }

    mainLabel.text = (NSString*)kCellTitles[indexPath.section][indexPath.row];
    valueLabel.text = [self tableView: tableView valueLabelTextForRowAtIndexPath: indexPath];

    return cell;
}
jessecurry
I'm finding that this approach isn't sufficient for my needs. I have a cell which has a multi-line title and multi-line description and autoresizes itself based on the text contained in the two labels. I'm sizing things in -(void)layoutSubviews and remembering to call [super layoutSubviews] first, but it seems to me that self.contentView is still not resizing until after this call, and thus sometimes my cells end up the wrong height.
Johnus