Skip to content

Instantly share code, notes, and snippets.

@tomkrush
Forked from henrik/README.markdown
Created June 6, 2010 17:06
Show Gist options
  • Save tomkrush/427714 to your computer and use it in GitHub Desktop.
Save tomkrush/427714 to your computer and use it in GitHub Desktop.

Rounded rectangle with gradient background on the iPhone, NSTokenFieldCell style.

Screenshot

Unlike my previous implementation, this one is drawn inside a single view using Core Graphics. It can thus be used for optimized, fast-scrolling cells per Apple's TableViewSuite sample.

The gradient shades are changed from that implementation, too, and the border itself is gradiented (by drawing a smaller rectangle inside a larger one that becomes the border).

You need to include the uicolor-utilities category by Ars Technica.

// ViewContainingToken.h
// By Henrik Nyh <http://henrik.nyh.se> 2010-04-01 under the MIT license.
// http://gist.github.com/352307
#import <UIKit/UIKit.h>
@interface ViewContainingToken : UIView {
}
@end
#import "ViewContainingToken.h"
// Include this: http://github.com/ars/uicolor-utilities/
#import "UIColor-Expanded.h"
@interface ViewContainingToken (Private)
- (void)drawTokenInRect:(CGRect)rect color:(UIColor *)color text:(NSString *)text;
@end
@implementation ViewContainingToken
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.opaque = YES;
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
#pragma mark -
- (void)drawRect:(CGRect)rect {
[self drawTokenInRect:CGRectMake(7, 12, 62, 22) color:[UIColor purpleColor] text:@"Hello!"];
}
#pragma mark -
void AKCGGradientRoundedRectCreate(CGContextRef context, CGRect rect,
CGColorSpaceRef colorspace, CGColorRef firstColor, CGColorRef lastColor);
- (void)drawTokenInRect:(CGRect)rect color:(UIColor *)color text:(NSString *)text {
// Rounded rectangle
UIColor *bottomColor = color;
UIColor *topColor = [bottomColor colorByMultiplyingBy:1.07];
UIColor *borderTopColor = [bottomColor colorByMultiplyingBy:0.95];
UIColor *borderBottomColor = [bottomColor colorByMultiplyingBy:0.85];
// We draw a lighter gradient rectangle inside a darker gradient rectangle to get a gradient border.
CGRect outerRect = rect;
CGRect innerRect = CGRectInset(outerRect, 1, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
AKCGGradientRoundedRectCreate(context, outerRect, colorspace, borderTopColor.CGColor, borderBottomColor.CGColor);
AKCGGradientRoundedRectCreate(context, innerRect, colorspace, topColor.CGColor, bottomColor.CGColor);
CGColorSpaceRelease(colorspace);
// Text inside the rectangle
UIFont *labelFont = [UIFont systemFontOfSize:12];
CGRect labelRect = CGRectInset(innerRect, 3, 2);
CGRect labelShadowRect = CGRectOffset(labelRect, 0, 1);
// Text shadow
[[UIColor whiteColor] set];
[text drawInRect:labelShadowRect
withFont:labelFont
lineBreakMode:UILineBreakModeMiddleTruncation
alignment:UITextAlignmentCenter];
// Text proper
[[UIColor blackColor] set];
[text drawInRect:labelRect
withFont:labelFont
lineBreakMode:UILineBreakModeMiddleTruncation
alignment:UITextAlignmentCenter];
CGMutablePathRef AKCGRoundedRectCreate(CGRect rect, CGFloat radius);
void AKCGGradientRoundedRectCreate(CGContextRef context, CGRect rect,
CGColorSpaceRef colorspace, CGColorRef firstColor, CGColorRef lastColor) {
CGFloat radius = rect.size.height/2;
CGMutablePathRef path = AKCGRoundedRectCreate(rect, radius);
CGContextAddPath(context, path);
CGContextSaveGState(context);
CGContextClip(context);
CGColorRef colors[] = {firstColor, lastColor};
CFArrayRef colorsArray = CFArrayCreate(NULL, (void *)colors, 2, &kCFTypeArrayCallBacks);
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, colorsArray, NULL);
CGPoint startPoint = rect.origin;
CGPoint endPoint = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CFRelease(colorsArray);
CGGradientRelease(gradient);
CGContextRestoreGState(context);
CGPathRelease(path);
}
CGMutablePathRef AKCGRoundedRectCreate(CGRect rect, CGFloat radius) {
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath, NULL, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect));
CGPathAddArc(thePath, NULL, CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect) + radius, radius, 3 * M_PI / 2, 0, 0);
CGPathAddArc(thePath, NULL, CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius, radius, 0, M_PI / 2, 0);
CGPathAddArc(thePath, NULL, CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius, radius, M_PI / 2, M_PI, 0);
CGPathAddArc(thePath, NULL, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect) + radius, radius, M_PI, 3 * M_PI / 2, 0);
CGPathCloseSubpath(thePath);
return thePath;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment