2013-03-08 117 views
5

我一直在尝试从UINavigationBar复制梯度以用作同一视图上自定义UIButton子类对象的渐变。如何复制UINavigationBar的渐变颜色?

但是,我无法弄清楚颜色是如何派生的?也就是说,您只指定一种颜色来设置UINavigationBar的背景颜色 - tintColor - 但它创建了一个很好的渐变效果,至少有4种颜色?

虽然我真的只是对“内部”顶部和底部颜色感兴趣 - 只是在酒吧周围的1px边框内......外部“边框”颜色确实显得不同。

编辑 - 1

经进一步研究,它出现在HSB(而不是作为RBG首先想到的)值是被操纵来获得这些不同的颜色。

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

getHue:saturation:brightness:alpha: 

有益的参考迄今发现

HSL and HSV Wiki

UIColor Class Reference

Programmatically Lighten a Color

From the book Fundamentals of Interactive Computer Graphics

编辑 - 2

如果你不知道,你可以设置一个UIButton编程背景的梯度,这里是如何做到这样的一些参考:

FUN WITH UIBUTTONS AND CORE ANIMATION LAYERS

Five Tips for Creating Stylish UIButtons(荣获@cdo提供此链接)

编辑 - 3

我已经把一个电子表格示出原始和“内”渐变颜色(不考虑最外层颜色)上UINavigationBar在HSB值和与其对应的“后退”按钮(标题是无关的,并始终显示白色)。

这里有一个链接到谷歌文档与我收集了几个样品的颜色信息:

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

注:使用视网膜保存截图发现这些值,3.5"用于iOS 6.1的iPhone模拟器(Xcode版本4.6),并使用PhotoShop注视HSB值。

BOUNTY奖励标准

我已经开了一个赏金对这一问题带来更多的接触到它,并希望得到一个很好的答案。我正在寻找的答案:

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

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

+0

太晚了赏金,但希望有人会发现我的回答有用反正... – danh 2013-03-12 02:46:57

回答

7

短答案:它不梯度

龙答案:施加着色颜色后,没有呈现在它的上面的透明覆盖图像。

它被称为:[email protected]它是在UIKit的艺术品。 (上传于:http://cl.ly/image/2c2V3t1D1T3L

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

对于后退按钮,它非常相似,但也有一个掩模来赋予其形状。 UItintedBackButtonHighlight和UITintedBackButtonMask。

+1

你在哪里/你是如何找到这张图片的? – 2013-03-11 21:44:15

+0

要回答我自己的问题,这是有帮助的:https://github.com/0xced/UIKit-Artwork-Extractor – 2013-03-12 00:00:59

+0

这是我去的解决方案。在我的情况下,我创建了一个更大(更大的高度)图像渐变,并添加为按钮的叠加层。奖金时限过后,我会奖励赏金。 – 2013-03-12 00:04:50

0

UIButton需要一个tintColor属性,但这并不意味着它不会计算其他颜色以用于幕后的渐变。 Try this tutorial

+0

感谢您的输入,但这个答案是误导和不正确诚实...(1)'tintColor'在按下*颜色上设置*,这是一种**实体**(非渐变)颜色,(2)'UIButton'上有'backgroundColor'属性,如果按钮类型是'UIButtonTypeCustom',但它仍然是纯色,(3)是的,如果试图将渐变应用于按钮(该**必须通过添加渐变图层来完成),则教程链接将会很有帮助,据我所知),但问题是这仍然无助于确定正确的颜色来模拟导航栏渐变。 – 2013-03-10 00:26:24

+0

我可以看到,这个问题可能是误导性的,因为'UIButton'和'UINavigationBar'确实具有'tintColor'属性,所以我编辑了这个问题以使其更加清晰。再次感谢您的输入。 – 2013-03-10 00:28:52

+0

+1对于链接...我也将它作为编辑添加到问题 – 2013-03-10 00:39:27

2

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

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

要创建我用PaintCode一个很好的工具,顺便说一句原型此示例代码..
复制这个代码在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); 
} 
+0

我最初有这个想法(更改RGB值),但我不认为苹果是这样做的(我的猜测是他们改变HSB值 - 特别是饱和度和亮度)。然而,+1,因为这似乎是*相似* ...我希望有点接近苹果的颜色,虽然。 – 2013-03-11 18:11:19

+0

我真的试图操纵色调,suration和亮度,但结果不是很好,因为这一个。 (只需加载演示应用程序并自己尝试一下,就可以实现你想要的那种子颜色操作,例如,使用相同的饱和度操作无法处理turquite和orange。而且,Apple似乎对一堆颜色使用了不同的计算方法。 – 2013-03-11 19:24:57

2

感谢您的好问题和慷慨的赏金。我去了解这一点,忽略了检查,看看它已经可以接受。然而,它是有趣的建设和测试以下导航栏类别,揭示它的颜色...

// 
// 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); 
} 
+0

+1:整洁的解决方案 - 以编程方式查询导航栏。 – 2013-03-12 16:41:29

+0

谢谢。 :-)发布后,它可以很容易地成为一个UIView类别,从任何视图的任何位置回答任何颜色。只需将UINavigationBar(Colors)更改为UIView(Colors)。 – danh 2013-03-12 16:55:05