UITableViewCell with alternate background color in customized cells

10,325

Solution 1

It is very simple, the indexPath tells you everything you need to know. If the indexPath.row is even then use one color. If the indexPath.row is odd use a different color.

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    …

    // SETTING BACKGROUND COLOR

    //        UIView *lab = [[UIView alloc] initWithFrame:cell.frame];
    //        [lab setBackgroundColor:[UIColor blueColor]];

    if (indexPath.row % 2) {
        cell.contentView.backgroundColor = [[[UIColor alloc]initWithRed:87.0/255.0 green:84.0/255.0 blue:229.0/255.0 alpha:1] autorelease];
    } else {
        cell.contentView.backgroundColor = [[[UIColor alloc]initWithRed:187.0/255.0 green:184.0/255.0 blue:229.0/255.0 alpha:1] autorelease];
    }

    …

    return cell;
}

Your method is having problems because blindly assuming cells will be asked for in alternating pairs is a bad assumption. The tableView could ask for cells in any order is chooses. In your example, I believe cells could be asked for as follows. First, 0, 1,…, 9 are asked for. Next, you scroll down and 10, 11, and 12 are fetched. At this point, 0, 1, and 2 have gone off the screen. You scroll back up and 2 is asked for, but oh no, your model is on an odd number alternation, so you get the wrong color.

Solution 2

Use the -willDisplayCell method.

- (void)tableView: (UITableView *)tableView willDisplayCell: (UITableViewCell *)cell forRowAtIndexPath: (NSIndexPath *)indexPath {

    if (indexPath.row %2) { //change the "%2" depending on how many cells you want alternating.
        UIColor *altCellColor = [UIColor colorWithRed:255/255.0 green:237/255.0 blue:227/255.0 alpha:1.0]; //this can be changed, at the moment it sets the background color to red.
        cell.backgroundColor = altCellColor;
    }
    else if (indexPath.row %2) { 
        UIColor *altCellColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1.0]; //this can be changed, at the moment it sets the background color to white.
        cell.backgroundColor = altCellColor2;
    }
}
Share:
10,325
DevonDahon
Author by

DevonDahon

Updated on June 27, 2022

Comments

  • DevonDahon
    DevonDahon almost 2 years

    I'd like the background to of my UITableViewCells to have a different color every two cells displayed, but when I scroll down and back, they all get the same color. How can I get this effect knowing that my cells have different contentView size (according to their content) ?

    #define FONT_SIZE 14.0f
    #define CELL_CONTENT_WIDTH 320.0f
    #define CELL_CONTENT_MARGIN 20.0f
    #define NAME_CELL_HEIGHT 20.0f
    
    #import "CartCell.h"
    
    @implementation CartCell
    
    @synthesize nameLabel = _nameLabel;
    @synthesize ingredientsLabel = _ingredientsLabel;
    @synthesize myStore;
    
    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
    
        myStore = [Store sharedStore];
    
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
    
            self.nameLabel = nil;
            self.ingredientsLabel = nil;
    
            // SET "NAME" CELL
            self.nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
            [self.nameLabel setLineBreakMode:UILineBreakModeWordWrap];
            [self.nameLabel setMinimumFontSize:FONT_SIZE];
            [self.nameLabel setNumberOfLines:1];
            [self.nameLabel setTag:1];
            self.nameLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:18];
            [self.nameLabel sizeToFit];
            self.nameLabel.backgroundColor = [UIColor clearColor];
            [[self contentView] addSubview:self.nameLabel];
    
            // SET "INGREDIENTS" CELL
            self.ingredientsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
            [self.ingredientsLabel setLineBreakMode:UILineBreakModeWordWrap];
            [self.ingredientsLabel setMinimumFontSize:FONT_SIZE];
            [self.ingredientsLabel setNumberOfLines:0];
            [self.ingredientsLabel setFont:[UIFont systemFontOfSize:FONT_SIZE]];
            [self.ingredientsLabel setTag:2];
            self.ingredientsLabel.backgroundColor = [UIColor clearColor];
            [[self contentView] addSubview:self.ingredientsLabel];
    
            if (myStore.cellBackgroundShouldBeLight == YES) {
                NSLog(@"clear [in] ? %@", myStore.cellBackgroundShouldBeLight ? @"Yes" : @"No");
                self.contentView.backgroundColor = [[UIColor alloc]initWithRed:87.0/255.0 green:168.0/255.0 blue:229.0/255.0 alpha:1];
                myStore.cellBackgroundShouldBeLight = NO;
            } else {
                NSLog(@"clear [in] ? %@", myStore.cellBackgroundShouldBeLight ? @"Yes" : @"No");
                self.contentView.backgroundColor = [[UIColor alloc]initWithRed:187.0/255.0 green:268.0/255.0 blue:229.0/255.0 alpha:1];
                myStore.cellBackgroundShouldBeLight = YES;
            }
    
        }
    
        return self;
    }
    
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated
    {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    
    @end
    

    UPDATE:

    I'm know trying to set it in cellForRowAtIndexPath as it was suggested, but I get the same result: scrolling down worked fine the first time, but then scrolling up again messed up the cells background color.

    - (UITableViewCell *)tableView:(UITableView *)tableView
             cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        static NSString *CellIdentifier = @"CartCell";
        CartCell *cell = (CartCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        Recipes *info = [_fetchedResultsController objectAtIndexPath:indexPath];
    
        if (cell == nil) 
        {
            cell = [[CartCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    
        }
    
    //    if (!cell.nameLabel) {
    //        cell.nameLabel = (UILabel*)[cell viewWithTag:1];
    //        //        cell.nameLabel = (UILabel*)[cell viewWithTag:1];
    //    }
    //    if (!cell.ingredientsLabel)
    //        cell.ingredientsLabel = (UILabel*)[cell viewWithTag:2];
    
        CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
        CGSize size = [info.ingredients sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
    
        [cell.nameLabel setFrame:CGRectMake(10, 10, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), NAME_CELL_HEIGHT)];
        [cell.ingredientsLabel setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN + NAME_CELL_HEIGHT, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
    
        // SETTING TEXT CONTENT
        cell.nameLabel.text = info.name;
        cell.ingredientsLabel.text = info.ingredients;
    
        // SETTING BACKGROUND COLOR
    
        //        UIView *lab = [[UIView alloc] initWithFrame:cell.frame];
        //        [lab setBackgroundColor:[UIColor blueColor]];
    
        if (myStore.cellBackgroundShouldBeLight == YES) {
            NSLog(@"clear? %@", myStore.cellBackgroundShouldBeLight ? @"Yes" : @"No");
            cell.contentView.backgroundColor = [[UIColor alloc]initWithRed:87.0/255.0 green:84.0/255.0 blue:229.0/255.0 alpha:1];
            //            cell.backgroundView = lab;
            //            ingredientsLabel.backgroundColor = [UIColor clearColor];
            //            nameLabel.backgroundColor = [[UIColor alloc]initWithRed:87.0/255.0 green:168.0/255.0 blue:229.0/255.0 alpha:1];
            //            [cell setBackgroundColor: [[UIColor alloc]initWithRed:87.0/255.0 green:168.0/255.0 blue:229.0/255.0 alpha:1]];
            //            [cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
            myStore.cellBackgroundShouldBeLight = NO;
        } else {
    //        cell.contentView.tag = 2;
            NSLog(@"clear? %@", myStore.cellBackgroundShouldBeLight ? @"Yes" : @"No");
            cell.contentView.backgroundColor = [[UIColor alloc]initWithRed:187.0/255.0 green:184.0/255.0 blue:229.0/255.0 alpha:1];
            myStore.cellBackgroundShouldBeLight = YES;
        }
    
    
        return cell;
    }
    
  • max_
    max_ almost 12 years
    This will cause a pretty big leak.
  • Jeffery Thomas
    Jeffery Thomas almost 12 years
    @max_ Not if he's using ARC, but I'll add the autorelease.
  • max_
    max_ almost 12 years
    @jeffery_thomas, UIColor has an autoreleased method, you should be using that instead. [UIColor colorWithRed...];
  • Jeffery Thomas
    Jeffery Thomas almost 12 years
    @max_ Yes I know that, personally I never use alloc/init for colors, but that's not what the original poster used. I try to stick with the original code as close as possible. I like for people to only see the required change.
  • bryanmac
    bryanmac over 11 years
    also - you may have to do cell.textLabel.backgroundColor = [UIColor clearColor] to see through to the bg color.
  • Simo
    Simo almost 11 years
    @jeffery I added a comment as answer below because it's too long :)