Alternating Rows for UITableView

Tables support in iPhone is thought out well but it seems that due to the complexity of the issue they have dropped out support for alternating rows. I suppose that this is a popular feature so I've written a subclass of UITableViewController that could be used as a drop-in replacement that changes background color of the odd rows.

AltTableViewController.h

#import <UIKit/UIKit.h>

@interface AltTableViewController : UITableViewController {
  UIColor *primRowColor, *altRowColor;
}

@property(retain) UIColor *primRowColor, *altRowColor;

- (BOOL)isAltRow:(NSIndexPath *)indexPath;
- (void)updateRowsLook;

@end

AltTableViewController.m

#import "AltTableViewController.h"

@implementation AltTableViewController

@synthesize primRowColor, altRowColor;

+ (UIColor *)defaultAltRowColor {
  static UIColor *color;

  if (!color) {
    color = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.05];
  }
  return color;
}

- (UIColor *)altRowColor {
  return altRowColor ? altRowColor :
      [AltTableViewController defaultAltRowColor];
}

- (UIColor *)primRowColor {
  return primRowColor ? primRowColor : [UIColor whiteColor];
}

- (void)dealloc {
  [altRowColor release];
  [primRowColor release];
  [super dealloc];
}

- (BOOL)isAltRow:(NSIndexPath *)indexPath {
  return indexPath.row == 0 || indexPath.row % 2 == 0;
}

- (void)updateRowsLookLater {
  NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
  if (indexPaths) {
    for (NSIndexPath *indexPath in indexPaths) {
      if ([self isAltRow:indexPath]) {
        [self.tableView cellForRowAtIndexPath:indexPath].backgroundColor =
            self.altRowColor;
      } else {
        [self.tableView cellForRowAtIndexPath:indexPath].backgroundColor =
            self.primRowColor;
      }
    }
  }
}

- (void)updateRowsLook {
  [self performSelector:@selector(updateRowsLookLater)
      withObject:nil afterDelay:0.01];
}

- (void)tableView:(UITableView *)tableView
        willDisplayCell:(UITableViewCell *)cell
        forRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([self isAltRow:indexPath]) {
        cell.backgroundColor = self.altRowColor;
    } else {
        cell.backgroundColor = self.primRowColor;
  }
}

- (void)tableView:(UITableView *)tableView
    commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
    forRowAtIndexPath:(NSIndexPath *)indexPath {
  [self updateRowsLook];
}

- (void)tableView:(UITableView *)tableView
    moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
    toIndexPath:(NSIndexPath *)toIndexPath {
  [self updateRowsLook];
}

@end

Note that your cells should not contain labels with opaque backgrounds. Background color of the cell should be visible through labels.

I have also implemented methods that are called in response to editing actions since now deletion, insertion and rearrangement of a row impacts other rows. If your table will be editable you should call these methods to update backgrounds of all cells.

  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • LinkedIn
  • E-mail this story to a friend!
  • Print this article!

blog comments powered by Disqus