I have been trying to put a gradient to my table view cells background with several ways and none seem to work. I've been trying to draw it with quarz core graphics thing, putting background outlet to a different view on IB, putting imageview on the back with code. None seem to show up on the back somehow, I don't get what is wrong. I can elaborate if needed, thanks!
Asked
Active
Viewed 2,072 times
1 Answers
2
I found some code in this question and adapted it to work with my application. It works great with both plain and grouped tables.
//
// UAGradientCellBackgroundLayer.h
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@class UAGradientCellBackgroundView;
@interface UAGradientCellBackgroundLayer : CAGradientLayer {
CGFloat *colorComponents;
BOOL _override;
}
@property(nonatomic,assign) BOOL override;
- (void)setColorComponents:(CGFloat *)components;
@end
//
// UAGradientCellBackgroundLayer.m
//
#import "UAGradientCellBackgroundLayer.h"
#import "UAGradientCellBackgroundView.h"
#define TABLE_CELL_BACKGROUND {1, 1, 1, 1, 204/255.0, 204/255.0, 204/255.0, 1} // #FFFFFF and #DDDDDD
@implementation UAGradientCellBackgroundLayer
@synthesize override = _override;
///////////////////////////////////////////////////////////////////////////////////////////////////
- (id)init {
if ((self = [super init])) {
colorComponents = NSZoneMalloc(NSDefaultMallocZone(), 8*sizeof(CGFloat));
CGFloat c[8] = TABLE_CELL_BACKGROUND;
for (int i = 0; i < 8; i++) {
colorComponents[i] = c[i];
}
// self.cornerRadius = 10;
// self.backgroundColor = [UIColor clearColor].CGColor;
}
return self;
}
- (void) dealloc {
NSZoneFree(NSDefaultMallocZone(), colorComponents);
[super dealloc];
}
- (void)display {
if (_override) {
self.colors =
[NSArray arrayWithObjects:
(id)[UIColor colorWithRed:colorComponents[0] green:colorComponents[1] blue:colorComponents[2] alpha:colorComponents[3]].CGColor,
(id)[UIColor colorWithRed:colorComponents[4] green:colorComponents[5] blue:colorComponents[6] alpha:colorComponents[7]].CGColor,
nil];
} else {
self.colors =
[NSArray arrayWithObjects:
(id)[UIColor clearColor].CGColor,
(id)[UIColor clearColor].CGColor,
nil];
}
[super display];
}
- (void)setColorComponents:(CGFloat *)components {
for (int i = 0; i < 8; i++) {
colorComponents[i] = components[i];
}
}
@end
//
// UAGradientCellBackgroundView.h
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum {
UAGradientCellBackgroundViewPositionMiddle = 0,
UAGradientCellBackgroundViewPositionTop,
UAGradientCellBackgroundViewPositionBottom,
UAGradientCellBackgroundViewPositionSingle,
UAGradientCellBackgroundViewPositionPlain
} UAGradientCellBackgroundViewPosition;
@interface UAGradientCellBackgroundView : UIView {
UAGradientCellBackgroundViewPosition position;
CGFloat colors[8];
}
@property(nonatomic, assign) UAGradientCellBackgroundViewPosition position;
- (void)setColors:(CGFloat[8])comps;
@end
//
// UAGradientCellBackgroundView.m
//
#import "UAGradientCellBackgroundView.h"
#import "UAGradientCellBackgroundLayer.h"
#import <QuartzCore/QuartzCore.h>
#define kDefaultMargin 10
#define TABLE_CELL_BACKGROUND {1, 1, 1, 1, 204/255.0, 204/255.0, 204/255.0, 1} // #FFFFFF and #DDDDDD
static void addRoundedRectToPath(CGContextRef context, CGRect rect,
float ovalWidth,float ovalHeight);
@implementation UAGradientCellBackgroundView
@synthesize position;
//////////////////////////////////////////////////////////////////////
// PLAIN CELL
//
// layerClass
//
// returns a CAGradientLayer class as the default layer class for this view
//
+ (Class)layerClass {
return [UAGradientCellBackgroundLayer class];
}
//////////////////////////////////////////////////////////////////////
- (void)updateLayer {
UAGradientCellBackgroundLayer* layer = (UAGradientCellBackgroundLayer*)self.layer;
// This is dramatically faster than calling drawRect.
[layer setColorComponents:colors];
layer.override = (self.position == UAGradientCellBackgroundViewPositionPlain);
[layer setNeedsDisplay];
}
////////////////////////////////////////////////////////////////////
// GROUPED CELL
- (void)setColors:(CGFloat[8])comps {
for (int i = 0; i < 8; i++) {
colors[i] = comps[i];
}
}
- (BOOL)isOpaque {
return YES;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self != nil) {
CGFloat comps[8] = TABLE_CELL_BACKGROUND;
[self setColors:comps];
}
return self;
}
- (void)debugView:(UIView *)view {
NSLog(@"%@ - %@", view.backgroundColor, [[view class] description]);
for (UIView* child in view.subviews) {
[self debugView:child];
}
}
-(void)drawRect:(CGRect)aRect {
[super drawRect:aRect];
// Drawing code
if (position == UAGradientCellBackgroundViewPositionPlain) {
return;
}
CGContextRef c = UIGraphicsGetCurrentContext();
// TODO - Dirty, Dirty hack to fix the background black corners on pop issue. doesnt handle rotation.
// CGContextSetFillColorWithColor(c, [UAColor offsetPinstripesColor].CGColor);
// CGContextFillRect(c, aRect);
int lineWidth = 1;
CGRect rect = [self bounds];
rect.size.width -= lineWidth;
rect.size.height -= lineWidth;
rect.origin.x += lineWidth / 2.0;
rect.origin.y += lineWidth / 2.0;
CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect);
CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect);
miny -= 1;
CGFloat locations[2] = { 0.0, 1.0 };
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = nil;
CGContextSetStrokeColorWithColor(c, [UIColor darkGrayColor].CGColor);
CGContextSetLineWidth(c, lineWidth);
CGContextSetAllowsAntialiasing(c, YES);
CGContextSetShouldAntialias(c, YES);
if (position == UAGradientCellBackgroundViewPositionTop) {
miny += 1;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, maxy);
CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, maxy, kDefaultMargin);
CGPathAddLineToPoint(path, NULL, maxx, maxy);
CGPathAddLineToPoint(path, NULL, minx, maxy);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGPathRelease(path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UAGradientCellBackgroundViewPositionBottom) {
//maxy -= 1; // -1 for the shadow
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, miny);
CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kDefaultMargin);
CGPathAddLineToPoint(path, NULL, maxx, miny);
CGPathAddLineToPoint(path, NULL, minx, miny);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGPathRelease(path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UAGradientCellBackgroundViewPositionMiddle) {
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, miny);
CGPathAddLineToPoint(path, NULL, maxx, miny);
CGPathAddLineToPoint(path, NULL, maxx, maxy);
CGPathAddLineToPoint(path, NULL, minx, maxy);
CGPathAddLineToPoint(path, NULL, minx, miny);
CGPathCloseSubpath(path);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGPathRelease(path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
} else if (position == UAGradientCellBackgroundViewPositionSingle) {
miny += 1;
//maxy -= 1; // -1 for the shadow
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, midy);
CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, midy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, maxy, midx, maxy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, minx, maxy, minx, midy, kDefaultMargin);
CGPathCloseSubpath(path);
// Shadow
// CGContextAddPath(c, path);
// CGContextSaveGState(c);
// CGContextSetShadow(c, CGSizeMake(0, -1), 1);
// CGContextFillPath(c);
// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);
myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);
CGContextAddPath(c, path);
CGPathRelease(path);
CGContextStrokePath(c);
CGContextRestoreGState(c);
}
CGColorSpaceRelease(myColorspace);
CGGradientRelease(myGradient);
return;
}
- (void)setPosition:(UAGradientCellBackgroundViewPosition)newPosition {
if (position != newPosition) {
position = newPosition;
[self updateLayer];
}
}
@end
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,float ovalHeight) {
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {// 1
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);// 2
CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3
CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4
fw = CGRectGetWidth (rect) / ovalWidth;// 5
fh = CGRectGetHeight (rect) / ovalHeight;// 6
CGContextMoveToPoint(context, fw, fh/2); // 7
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11
CGContextClosePath(context);// 12
CGContextRestoreGState(context);// 13
}
Usage sample (plain table):
#import "UAGradientCellBackgroundView.h"
CGFloat COLORS[8] = { 0.0/255, 0.0/255, 255.0/255, 1.0, 0.0/255, 0.0/255, 0.0/255, 1.0 }
...
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellID = @"CellID";
// create cell
UITableViewCell *cell = (UITableViewCell *)[table dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease];
UAGradientCellBackgroundView *bgView = [[[UAGradientCellBackgroundView alloc] initWithFrame:CGRectZero] autorelease];
[bgView setBackgroundColor:[UIColor clearColor]];
[bgView setColors:COLORS];
[bgView setPosition:UAGradientCellBackgroundViewPositionPlain];
cell.selectedBackgroundView = bgView;
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.imageView.image = [UIImage imageNamed:@"cellimg.png"];
}
cell.textLabel.text = @"Text";
return cell;
}
-
If I try to set it as background view it only makes the cell seperators darker, I don't get why it won't work as background view, but it works as selected view? – Samuli Lehtonen Nov 19 '10 at 21:32
-
Umm... changing `selectedBackgroundView` to `backgroundView` works just fine for me, there's probably some other issue in your code or you made some other changes to the code pasted. Maybe you're setting both the background color and the background view for the cells? Or you have several types of cells with different gradients and you're not using different cell IDs? -- these are just two problems I ran into at some point. – cristis Nov 19 '10 at 22:06