3

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;
}
DevonDahon
  • 7,460
  • 6
  • 69
  • 114

7 Answers7

20

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.

bryanmac
  • 38,941
  • 11
  • 91
  • 99
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
  • This will cause a pretty big leak. – max_ Jun 23 '12 at 13:15
  • @max_ Not if he's using ARC, but I'll add the autorelease. – Jeffery Thomas Jun 23 '12 at 13:25
  • @jeffery_thomas, `UIColor` has an autoreleased method, you should be using that instead. `[UIColor colorWithRed...];` – max_ Jun 23 '12 at 13:29
  • @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. – Jeffery Thomas Jun 23 '12 at 13:45
  • also - you may have to do cell.textLabel.backgroundColor = [UIColor clearColor] to see through to the bg color. – bryanmac Oct 08 '12 at 12:30
  • @jeffery I added a comment as answer below because it's too long :) – Simo May 14 '13 at 16:40
1

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;
    }
}
max_
  • 24,076
  • 39
  • 122
  • 211
0

The appropriate place to change your cell's background color would be the "cellForRowAtIndexPath:" method, where the cells data gets filled out and returned to the table view.

One way to do this would be: When the data goes into the cell, change the background color depending on what row you're on.

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
0

Put the color on the cellForRowAtIndexPath: don't set on custom cell.

Manikandan K
  • 117
  • 14
0

Take a look what I use to customize my table

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
#if USE_CUSTOM_DRAWING
    const NSInteger TOP_LABEL_TAG = 1001;
    const NSInteger BOTTOM_LABEL_TAG = 1002;
    UILabel *topLabel;
    UILabel *bottomLabel;
#endif

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        //
        // Create the cell.
        //
        cell =
            [[[UITableViewCell alloc]
                initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
            autorelease];

#if USE_CUSTOM_DRAWING
        UIImage *indicatorImage = [UIImage imageNamed:@"indicator.png"];
        cell.accessoryView =
            [[[UIImageView alloc]
                initWithImage:indicatorImage]
            autorelease];

        const CGFloat LABEL_HEIGHT = 20;
        UIImage *image = [UIImage imageNamed:@"imageA.png"];

        //
        // Create the label for the top row of text
        //
        topLabel =
            [[[UILabel alloc]
                initWithFrame:
                    CGRectMake(
                        image.size.width + 2.0 * cell.indentationWidth,
                        0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT),
                        aTableView.bounds.size.width -
                            image.size.width - 4.0 * cell.indentationWidth
                                - indicatorImage.size.width,
                        LABEL_HEIGHT)]
            autorelease];
        [cell.contentView addSubview:topLabel];

        //
        // Configure the properties for the text that are the same on every row
        //
        topLabel.tag = TOP_LABEL_TAG;
        topLabel.backgroundColor = [UIColor clearColor];
        topLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
        topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
        topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];

        //
        // Create the label for the top row of text
        //
        bottomLabel =
            [[[UILabel alloc]
                initWithFrame:
                    CGRectMake(
                        image.size.width + 2.0 * cell.indentationWidth,
                        0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT) + LABEL_HEIGHT,
                        aTableView.bounds.size.width -
                            image.size.width - 4.0 * cell.indentationWidth
                                - indicatorImage.size.width,
                        LABEL_HEIGHT)]
            autorelease];
        [cell.contentView addSubview:bottomLabel];

        //
        // Configure the properties for the text that are the same on every row
        //
        bottomLabel.tag = BOTTOM_LABEL_TAG;
        bottomLabel.backgroundColor = [UIColor clearColor];
        bottomLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
        bottomLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
        bottomLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 2];

        //
        // Create a background image view.
        //
        cell.backgroundView =
            [[[UIImageView alloc] init] autorelease];
        cell.selectedBackgroundView =
            [[[UIImageView alloc] init] autorelease];
#endif
    }

#if USE_CUSTOM_DRAWING
    else
    {
        for (UIView *sub in [cell.contentView subviews]) {
//            if([sub class] == [UITableViewCellContentView class])
                NSLog(@"this is uilabel %@",[sub class]);
        }
        topLabel = (UILabel *)[cell viewWithTag:TOP_LABEL_TAG];
        bottomLabel = (UILabel *)[cell viewWithTag:BOTTOM_LABEL_TAG];
    }

    topLabel.text = [NSString stringWithFormat:@"Cell at row %ld.", [indexPath row]];
    bottomLabel.text = [NSString stringWithFormat:@"Some other information.", [indexPath row]];

    //
    // Set the background and selected background images for the text.
    // Since we will round the corners at the top and bottom of sections, we
    // need to conditionally choose the images based on the row index and the
    // number of rows in the section.
    //
    UIImage *rowBackground;
    UIImage *selectionBackground;
    NSInteger sectionRows = [aTableView numberOfRowsInSection:[indexPath section]];
    NSInteger row = [indexPath row];
    if (row == 0 && row == sectionRows - 1)
    {
        rowBackground = [UIImage imageNamed:@"topAndBottomRow.png"];
        selectionBackground = [UIImage imageNamed:@"topAndBottomRowSelected.png"];
    }
    else if (row == 0)
    {
        rowBackground = [UIImage imageNamed:@"topRow.png"];
        selectionBackground = [UIImage imageNamed:@"topRowSelected.png"];
    }
    else if (row == sectionRows - 1)
    {
        rowBackground = [UIImage imageNamed:@"bottomRow.png"];
        selectionBackground = [UIImage imageNamed:@"bottomRowSelected.png"];
    }
    else
    {
        rowBackground = [UIImage imageNamed:@"middleRow.png"];
        selectionBackground = [UIImage imageNamed:@"middleRowSelected.png"];
    }
    ((UIImageView *)cell.backgroundView).image = rowBackground;
    ((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
//  cell.backgroundView.backgroundColor = [UIColor colorWithPatternImage:rowBackground];
//    cell.selectedBackgroundView.backgroundColor = [UIColor colorWithPatternImage:selectionBackground];
    //
    // Here I set an image based on the row. This is just to have something
    // colorful to show on each row.
    //
    if ((row % 3) == 0)
    {
        cell.imageView.image = [UIImage imageNamed:@"imageA.png"];
    }
    else if ((row % 3) == 1)
    {
        cell.imageView.image = [UIImage imageNamed:@"imageB.png"];
    }
    else
    {
        cell.imageView.image = [UIImage imageNamed:@"imageC.png"];
    }
#else
    cell.text = [NSString stringWithFormat:@"Cell at row %ld.", [indexPath row]];
#endif

    return cell;
}

past it after all #import lines

#define USE_CUSTOM_DRAWING 1
The iOSDev
  • 5,237
  • 7
  • 41
  • 78
0

Heading ##Simplest way of changing alternate colors


if(indexPath.row%2) {
    cell.backgroundColor=[UIColor nameUrColor] //brownColor, yellowColor, blueColor
} else {
    cell.backgroundColor=[UIColor nameAnotherColor]
}
Bob Vork
  • 2,927
  • 28
  • 32
AmazingAshu
  • 17
  • 1
  • 6
0
if(cell.contentView)
{
    [cell.nameLbl setFont:[UIFont systemFontOfSize:24]];
    int red_value = arc4random() % 210;
    int green_value = arc4random() % 210;
    int blue_value = arc4random() % 210;

    cell.contentView.backgroundColor = [UIColor colorWithRed:red_value/255.0 green:green_value/255.0 blue:blue_value/255.0 alpha:0.6];

}
User558
  • 1,165
  • 1
  • 13
  • 37