Search code examples
iosuitableviewdrawrect

How to refresh color of custom drawn cell?


I have custom UITableViewCell class which implements custom drawn design (as you can see, the cell has shadow effect.) As you can see below I'm trying to paint 1st cell with white color, any other cell must be gray.

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();

CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor;
if (_rowNumber == 0)
    CGColorRef lightColor = [UIColor whiteColor].CGColor;
else
    CGColorRef lightColor = [UIColor grayColor].CGColor;
CGColorRef darkColor = _darkColor.CGColor;
CGColorRef shadowColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:0.5].CGColor;
CGContextSetFillColorWithColor(context, whiteColor);

CGContextFillRect(context, _paperRect);
CGContextSaveGState(context);

CGContextSetShadowWithColor(context, CGSizeMake(0, 2), 7.0, shadowColor);
CGContextSetFillColorWithColor(context, lightColor);

CGContextFillRect(context, _coloredBoxRect);
CGContextRestoreGState(context); 
}

The problem is: when I'm using dequeueReusableCellWithIdentifier the method "drawRect" invoked only 3 times (my cells have height 200), so the fourth cell has same color like the first one.

Is there any way to manage this problem? Thanks

UPDATE i've tried to invoke my custom redraw method from UITableViewController, but i have got "null" context error

- (void)refreshColorOfRow:(int)row{
 CGContextRef context = UIGraphicsGetCurrentContext();
 if (row > 0)
     _lightColor = [UIColor colorWithRed:200.0f/255.0f green:199.0f/255.0f blue:200.0f/255.0f alpha:1.0];
 else
     _lightColor = [UIColor colorWithRed:240.0f/255.0f green:240.0f/255.0f blue:240.0f/255.0f alpha:1.0];
CGColorRef lightColor = _lightColor.CGColor;
CGContextSetFillColorWithColor(context, lightColor);
CGContextFillRect(context, _coloredBoxRect);
CGContextRestoreGState(context);
}

Solution

  • In -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath you could call [cell setNeedsDisplay];.

    But why don't you use [cell setBackgroundColor:[UIColor yourColorXY]]; if you only want some simple colors and shadows?

    EDIT: Like Guo Luchuan said, is an often called drawRect: a performance-killer. Just try it simple ;)

    NSIndexPath *selectedCell; //Declare this in your .h
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"CellIdentifier";
        UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier: CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
        }
        if (selectedCell.section==indexPath.section && selectedCell.row==indexPath.row) {
            [cell.contentView setBackgroundColor:[UIColor whiteColor]];
            [cell.textLabel setText:@"The Choosen One"];
        } else {
            [cell.contentView setBackgroundColor:[UIColor lightGrayColor]];
            [cell.textLabel setText:@"FOO"];
        }
        return cell;
    }
    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        selectedCell=indexPath;
        [tableView reloadData];
    }
    

    And for the shadows you can play around with..

    #import <QuartzCore/QuartzCore.h>
    
    CALayer *layer=[cell layer]; //Or [tableView layer] or whatever you need
    [layer setShadowColor:[[UIColor lightGrayColor] CGColor]];
    [layer setShadowOffset:CGSizeMake(1, 1)];
    [layer setShadowOpacity:1.0];
    [layer setMasksToBounds:NO];