我怎样才能复制UINavigationBar的渐变颜色?

我一直在尝试从UINavigationBar复制渐变,以在同一视图上用作自定义UIButton子类对象的渐变。

但是,我无法弄清楚颜色是如何派生的? 也就是说,你只指定一种颜色来设置一个UINavigationBar的背景颜色tintColor – 但是它创build了一个不错的渐变,至less有4种颜色?

我真的只是对“内部”的顶部和底部颜色感兴趣 – 只是在酒吧周围的1px边框内…外部的“边框”颜色确实看起来不同。

编辑 – 1

经过进一步的研究,似乎HSB(而不是RBG是第一个想法)价值被操纵,以获得这些不同的颜色。

UIColor上还有一个方便的方法来获取HSB值,这应该是有帮助的:

 getHue:saturation:brightness:alpha: 

有用的参考资料,迄今发现

HSL和HSV Wiki

UIColor类参考

以编程方式减轻颜色

从“ 交互式计算机graphics学基础 ”一书中

编辑 – 2

如果你不知道你可以在UIButton上以编程的方式设置背景的渐变,下面是一些如何做这样的参考:

用UIBUTTONS和核心animation层的乐趣

创build时尚的UIButtons的五个技巧 (荣获@cdo提供此链接)

编辑 – 3

UINavigationBar及其相应的“后退”button(标题无关紧要,总是显示为白色)中,我已经放在一起显示原始和“内部”渐变颜色(不考虑最外面的颜色)的电子表格。

以下是Google文档的链接,其中包含我收集的一些示例颜色的信息:

https://docs.google.com/spreadsheet/ccc?key=0AnKVtzkNS9scdGVRN01pa1NQcC1hdThNbEVzQU8wRlE&usp=sharing

注意:这些值是通过使用视网膜,3.5“iPhone模拟器(Xcode版本4.6)为iOS 6.1保存屏幕截图,并使用PhotoShop注视HSB值。

BOUNTY AWARD CRITERIA

我已经在这个问题上开了一个奖金,给它带来更多的曝光,并希望得到一个很好的答案。 我正在寻找的答案是:

提供一种方法,用于在UINavigationBar上设置tintColor后创build的“内部顶部”和“内部底部”渐变颜色(参见电子表格)的RGB或HSB值的计算/近似逼近(大多数情况下)。

如果您还提供了一种方法来计算“后退”button上的“内部顶部”和“内部底部”渐变颜色(类似于导航栏,但我已经发现这些方法)颜色通常会稍微“变暗”)?

简答:这不是渐变

长答案:在应用色调颜色之后,在其上面呈现透明的叠加图像。

它被称为:UITintedTopBarHighlight@2x.png它是在UIKit的艺术品。 (上传到这里: http : //cl.ly/image/2c2V3t1D1T3L )

它是2×88像素的图像,必须在有色背景上水平重复。

对于后退button,它是非常相似的,但也有一个面具给它的形状。 UItintedBackButtonHighlight和UITintedBackButtonMask。

这是很难复制的确切行为,因为它似乎苹果计算不同的颜色组。 例如。 浅色稍微变暗,深色变亮。

相同的酒吧button项目。 对于一些颜色,正常的“镶边”button和“完成”式button的区别是完全不同的。 有时候不会像绿松石那样引人注意,但是对橙色来说绝对是可以看到的。

为了创build这个示例代码,我使用了PaintCode一个很好的工具来构build原型。
将这段代码复制到一个UIView子类中。 或者只是抓住你需要的部分代码。

 - (void)drawRect:(CGRect)rect { //// General Declarations CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = UIGraphicsGetCurrentContext(); //// Color Declarations UIColor* tint = [UIColor colorWithRed: 1 green: 0.66 blue: 0.329 alpha: 1]; CGFloat tintRGBA[4]; [tint getRed: &tintRGBA[0] green: &tintRGBA[1] blue: &tintRGBA[2] alpha: &tintRGBA[3]]; UIColor* lighter = [UIColor colorWithRed: (tintRGBA[0] * 0.58 + 0.42) green: (tintRGBA[1] * 0.58 + 0.42) blue: (tintRGBA[2] * 0.58 + 0.42) alpha: (tintRGBA[3] * 0.58 + 0.42)]; CGFloat lighterRGBA[4]; [lighter getRed: &lighterRGBA[0] green: &lighterRGBA[1] blue: &lighterRGBA[2] alpha: &lighterRGBA[3]]; UIColor* lightest = [UIColor colorWithRed: (lighterRGBA[0] * 0.55 + 0.45) green: (lighterRGBA[1] * 0.55 + 0.45) blue: (lighterRGBA[2] * 0.55 + 0.45) alpha: (lighterRGBA[3] * 0.55 + 0.45)]; UIColor* darker = [UIColor colorWithRed: (tintRGBA[0] * 0.92) green: (tintRGBA[1] * 0.92) blue: (tintRGBA[2] * 0.92) alpha: (tintRGBA[3] * 0.92 + 0.08)]; CGFloat darkerRGBA[4]; [darker getRed: &darkerRGBA[0] green: &darkerRGBA[1] blue: &darkerRGBA[2] alpha: &darkerRGBA[3]]; UIColor* darkest = [UIColor colorWithRed: (darkerRGBA[0] * 0.65) green: (darkerRGBA[1] * 0.65) blue: (darkerRGBA[2] * 0.65) alpha: (darkerRGBA[3] * 0.65 + 0.35)]; //// Gradient Declarations NSArray* gradientColors = [NSArray arrayWithObjects: (id)lighter.CGColor, (id)darker.CGColor, nil]; CGFloat gradientLocations[] = {0, 1}; CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradientColors, gradientLocations); //// top Drawing UIBezierPath* topPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0, rect.size.width, 1)]; [lightest setFill]; [topPath fill]; //// theGradient Drawing UIBezierPath* theGradientPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 1, rect.size.width, rect.size.height - 1.0f)]; CGContextSaveGState(context); [theGradientPath addClip]; CGContextDrawLinearGradient(context, gradient, CGPointMake(50, 1), CGPointMake(50, rect.size.height-1.0f), 0); CGContextRestoreGState(context); //// bottom Drawing UIBezierPath* bottomPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, rect.size.height-1.0f, rect.size.width, 1)]; [darkest setFill]; [bottomPath fill]; //// Cleanup CGGradientRelease(gradient); CGColorSpaceRelease(colorSpace); } 

感谢好问题和慷慨的赏金。 我去了这个工作,忽略检查,看看它已经可以接受的答案。 不过,build立和testing以下导航栏类别非常有趣,它揭示了它的颜色。

 // // UINavigationBar+colors.h #import <UIKit/UIKit.h> @interface UINavigationBar (Colors) // Answer an array of colors representing the color of the reciever, starting at fromY, up to toY - (NSArray *)colorsFromY:(NSUInteger)fromY to:(NSUInteger)toY; @end 

与QuartzCore.framework链接。

 // // UINavigationBar+colors.m #import "UINavigationBar+colors.h" #import <QuartzCore/QuartzCore.h> #define UIIMAGE_BYTES_PER_PIXEL 4u @implementation UINavigationBar (Colors) + (NSData *)dataFromImage:(UIImage *)image { CGImageRef imageRef = [image CGImage]; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); NSUInteger dataSize = height * width * UIIMAGE_BYTES_PER_PIXEL; unsigned char *rawData = malloc(dataSize); NSUInteger bytesPerRow = width * UIIMAGE_BYTES_PER_PIXEL; NSUInteger bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGContextRelease(context); NSData *rtn = [NSData dataWithBytes:rawData length:dataSize]; free(rawData); return rtn; } + (UIColor *)colorOfImage:(UIImage *)image atX:(NSUInteger)px atY:(NSUInteger)py { NSData *imgData = [self dataFromImage:image]; if (!imgData) return nil; NSUInteger byteIndex = UIIMAGE_BYTES_PER_PIXEL * (image.size.width * py + px); unsigned char rgbaData[4]; NSRange range = { byteIndex, 4u }; [imgData getBytes:rgbaData range:range]; CGFloat red = rgbaData[0] / 255.0; CGFloat green = rgbaData[1] / 255.0; CGFloat blue = rgbaData[2] / 255.0; CGFloat alpha = rgbaData[3] / 255.0; return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; } - (UIImage *)asImage { UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0); [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return img; } - (NSArray *)colorsFromY:(NSUInteger)fromY to:(NSUInteger)toY { NSMutableArray *answer = [NSMutableArray array]; UIImage *image = [self asImage]; for (NSUInteger y = MAX(0, fromY); y < MIN(self.bounds.size.height, toY); y++) { [answer addObject:[self.class colorOfImage:image atX:1 atY:y]]; } return [NSArray arrayWithArray:answer]; } @end 

像这样调用它:

 // from a view controller contained by a navigation controller... UINavigationBar *bar = self.navigationController.navigationBar; NSArray *colors = [bar colorsFromY:0 to:bar.bounds.size.height]; for (UIColor *color in colors) { NSLog(@"%@", color); } 

UIButton只需要一个tintColor属性,但这并不意味着它不会计算其他颜色在后台渐变中的使用。 试试这个教程 。