kas-kad
kas-kad

Reputation: 3764

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);
}

Upvotes: 1

Views: 867

Answers (3)

xapslock
xapslock

Reputation: 1129

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];

Upvotes: 1

Guo Luchuan
Guo Luchuan

Reputation: 4731

I think you can make the first cell and other cells different identifier , such as first cells resueIdentifier is @"first" ; other cellss resueIdentifier is @"others" and then in your custom cell , you can creat a BOOL _isFirstCell to mark first cell and then in the - (void)drawRect:(CGRect)rect method , you can draw both type cell use if else statment

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

CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor;
if (_isFirstCell)
    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); 
}

Upvotes: 1

adig
adig

Reputation: 4057

I'm assuming you're setting _rowNumber as a property for your UITableViewCell subclass. You should call setNeedsDisplay in the setter to force redrawing :

-(void) setRowNumber:(int)value {
    _rowNumber = value;
    [self setNeedsDisplay];
}

Upvotes: 1

Related Questions