UITableViewCell with alternate background color in customized cells
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;
}
}
DevonDahon
Updated on June 27, 2022Comments
-
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_ almost 12 yearsThis will cause a pretty big leak.
-
Jeffery Thomas almost 12 years@max_ Not if he's using ARC, but I'll add the autorelease.
-
max_ almost 12 years@jeffery_thomas,
UIColor
has an autoreleased method, you should be using that instead.[UIColor colorWithRed...];
-
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 over 11 yearsalso - you may have to do cell.textLabel.backgroundColor = [UIColor clearColor] to see through to the bg color.
-
Simo almost 11 years@jeffery I added a comment as answer below because it's too long :)