如何复制UINavigationBar的渐变颜色?
我一直在尝试从UINavigationBar
复制梯度以用作同一视图上自定义UIButton
子类对象的渐变。如何复制UINavigationBar的渐变颜色?
但是,我无法弄清楚颜色是如何派生的?也就是说,您只指定一种颜色来设置UINavigationBar
的背景颜色 - tintColor
- 但它创建了一个很好的渐变效果,至少有4种颜色?
虽然我真的只是对“内部”顶部和底部颜色感兴趣 - 只是在酒吧周围的1px边框内......外部“边框”颜色确实显得不同。
编辑 - 1
经进一步研究,它出现在HSB(而不是作为RBG首先想到的)值是被操纵来获得这些不同的颜色。
还有上UIColor
一个方便的方法来获取HSB值,这应该是有帮助的:
getHue:saturation:brightness:alpha:
有益的参考迄今发现
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已经发现这些颜色通常会稍微“变暗”)?
短答案:它不梯度
龙答案:施加着色颜色后,没有呈现在它的上面的透明覆盖图像。
它被称为:[email protected]它是在UIKit的艺术品。 (上传于:http://cl.ly/image/2c2V3t1D1T3L)
它是2x88像素的图像,必须在有色背景上水平重复。
对于后退按钮,它非常相似,但也有一个掩模来赋予其形状。 UItintedBackButtonHighlight和UITintedBackButtonMask。
你在哪里/你是如何找到这张图片的? – 2013-03-11 21:44:15
要回答我自己的问题,这是有帮助的:https://github.com/0xced/UIKit-Artwork-Extractor – 2013-03-12 00:00:59
这是我去的解决方案。在我的情况下,我创建了一个更大(更大的高度)图像渐变,并添加为按钮的叠加层。奖金时限过后,我会奖励赏金。 – 2013-03-12 00:04:50
UIButton需要一个tintColor
属性,但这并不意味着它不会计算其他颜色以用于幕后的渐变。 Try this tutorial。
感谢您的输入,但这个答案是误导和不正确诚实...(1)'tintColor'在按下*颜色上设置*,这是一种**实体**(非渐变)颜色,(2)'UIButton'上有'backgroundColor'属性,如果按钮类型是'UIButtonTypeCustom',但它仍然是纯色,(3)是的,如果试图将渐变应用于按钮(该**必须通过添加渐变图层来完成),则教程链接将会很有帮助,据我所知),但问题是这仍然无助于确定正确的颜色来模拟导航栏渐变。 – 2013-03-10 00:26:24
我可以看到,这个问题可能是误导性的,因为'UIButton'和'UINavigationBar'确实具有'tintColor'属性,所以我编辑了这个问题以使其更加清晰。再次感谢您的输入。 – 2013-03-10 00:28:52
+1对于链接...我也将它作为编辑添加到问题 – 2013-03-10 00:39:27
很难复制确切的行为,因为它似乎是苹果计算不同的颜色组。例如。浅色稍微变暗,深色变亮。
相同的酒吧按钮项目。对于某些颜色,正常的“镶边”按钮和“完成”式按钮的区别完全不同。有时候不会像绿松石那样引人注意,但对橙色来说绝对可以看到。
要创建我用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);
}
我最初有这个想法(更改RGB值),但我不认为苹果是这样做的(我的猜测是他们改变HSB值 - 特别是饱和度和亮度)。然而,+1,因为这似乎是*相似* ...我希望有点接近苹果的颜色,虽然。 – 2013-03-11 18:11:19
我真的试图操纵色调,suration和亮度,但结果不是很好,因为这一个。 (只需加载演示应用程序并自己尝试一下,就可以实现你想要的那种子颜色操作,例如,使用相同的饱和度操作无法处理turquite和orange。而且,Apple似乎对一堆颜色使用了不同的计算方法。 – 2013-03-11 19:24:57
感谢您的好问题和慷慨的赏金。我去了解这一点,忽略了检查,看看它已经可以接受。然而,它是有趣的建设和测试以下导航栏类别,揭示它的颜色...
//
// 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);
}
+1:整洁的解决方案 - 以编程方式查询导航栏。 – 2013-03-12 16:41:29
谢谢。 :-)发布后,它可以很容易地成为一个UIView类别,从任何视图的任何位置回答任何颜色。只需将UINavigationBar(Colors)更改为UIView(Colors)。 – danh 2013-03-12 16:55:05
太晚了赏金,但希望有人会发现我的回答有用反正... – danh 2013-03-12 02:46:57