ThisDarkTao ThisDarkTao - 1 year ago 71
iOS Question

UITableViewCell subclass, how to draw buttons?

I'm making an app that needs three buttons in each tableview cell. I tried just adding the buttons to the cell using

addSubview
in
cellForRowAtIndexPath:
but this resulted in slow/janky scrolling with more than 6 or 7 rows.

I did some research online and have followed Apple's example of subclassing the UITableViewCell and drawing everything in
drawRect
. I can get text and images to draw perfectly, using
drawAtPoint
but this doesn't appear to work for UIButtons.

Adding the button as a subview of
[self contentView]
(in my subclasses
drawRect
) just results in even worse scroll lag than before.

Does anyone know how to get a button to draw properly within my UITableViewCell subclass?

Getting this right is crucial to the entire app so any help would be greatly appreciated!

UPDATE: Here is the code used for for
tableView:cellForRowAtIndexPath


static NSString *CellIdentifier = @"CustomCell";

AHCustomCell * cell = (AHCustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
AHCustomCell * customCell = [[[AHCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
customCell.frame = CGRectMake(0.0, 0.0, 320.0, 55.0);
cell = customCell;
}

Answer Source

The following code gives three buttons and no jaggy scrolling. Using tags, you can reset the text of the buttons depending on the row. This is illustrated for button 1 (which adjusts its title according to the row number). The button1Pressed: method illustrated figures out what row the button press came from. Hope this will be helpful.

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

    // see if there's a cell available to recylce
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell)
    {
        // there's no cell to recycle, so make a new one
        // add three buttons to it and tag them so we can alter their contents later

        cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier];

        UIButton* button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button1 setTitle:@"Button 1" forState:UIControlStateNormal];
        [button1 setFrame:CGRectMake(4.0, 15.0, 110, 30.0)];
        [button1 setTag:101];
        [button1 addTarget:self action:@selector(button1Pressed:) forControlEvents:UIControlEventTouchUpInside];
        [[cell contentView] addSubview:button1];

        UIButton* button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button2 setTitle:@"Button 2" forState:UIControlStateNormal];
        [button2 setFrame:CGRectMake(120.0, 15.0, 80.0, 30.0)];
        [button2 setTag:102];
        [button1 addTarget:self action:@selector(button2Pressed:) forControlEvents:UIControlEventTouchUpInside];
        [[cell contentView] addSubview:button2];

        UIButton* button3 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button3 setTitle:@"Button 3" forState:UIControlStateNormal];
        [button3 setFrame:CGRectMake(210, 15.0, 80.0, 30.0)];
        [button3 setTag:103];
        [button3 addTarget:self action:@selector(button3Pressed:) forControlEvents:UIControlEventTouchUpInside];
        [[cell contentView] addSubview:button3];

    }

    // either on a recycled cell or on the cell just created, set the contents

    UIButton* button1 = (UIButton*)[[cell contentView] viewWithTag:101];
    [button1 setTitle: [NSString stringWithFormat:@"Button 1 - %d", [indexPath row]] forState:UIControlStateNormal];

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}



- (void) button1Pressed: (UIButton*) button
{
   CGPoint buttonCentre = [button convertPoint:[button center] toView:[self tableView]];

    NSLog(@"Button 1 Pressed on row %d", [[[self tableView] indexPathForRowAtPoint:buttonCentre] row]);
}