在表格视图单元格背景上放置渐变
Posted
技术标签:
【中文标题】在表格视图单元格背景上放置渐变【英文标题】:Putting gradient on tableview cells background 【发布时间】:2010-11-19 18:51:41 【问题描述】:我一直在尝试通过多种方式为我的表格视图单元格背景添加渐变,但似乎都没有效果。我一直在尝试用石英核心图形的东西来绘制它,将背景插座放在 IB 上的不同视图中,将 imageview 放在后面,并带有代码。似乎没有人以某种方式出现在背面,我不明白出了什么问题。需要的我可以详细说明,谢谢!
【问题讨论】:
【参考方案1】:我在this question 中找到了一些代码,并对其进行了修改以适用于我的应用程序。它适用于普通表和分组表。
//
// 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
使用示例(普通表):
#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;
【讨论】:
如果我尝试将其设置为背景视图,它只会使单元格分隔符变暗,我不明白为什么它不能用作背景视图,但它可以用作选定视图? 嗯...将selectedBackgroundView
更改为backgroundView
对我来说效果很好,您的代码中可能存在其他问题,或者您对粘贴的代码进行了其他更改。也许您正在为单元格设置背景颜色和背景视图?或者您有几种类型的具有不同梯度的单元格并且您没有使用不同的单元格 ID? -- 这只是我在某个时候遇到的两个问题。以上是关于在表格视图单元格背景上放置渐变的主要内容,如果未能解决你的问题,请参考以下文章