我一直在尝试从UINavigationBar
复制渐变,以在同一视图上的自定义UIButton
子类对象上用作渐变。
然而,我无法弄清楚颜色是如何衍生出来的?也就是说,您只需指定一种颜色来设置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
及其相应的“后退”按钮上放置了显示原始和“内部”渐变颜色(忽略最外面的颜色)的电子表格(标题不相关并且始终显示)白色)。
以下是Google文档的链接,其中包含我为一些示例颜色收集的信息:
https://docs.google.com/spreadsheet/ccc?key=0AnKVtzkNS9scdGVRN01pa1NQcC1hdThNbEVzQU8wRlE&usp=sharing
注意:通过使用视网膜保存屏幕截图,使用适用于iOS 6.1的3.5英寸iPhone模拟器(Xcode版本4.6)以及使用PhotoShop关注HSB值,可以找到这些值。
BOUNTY AWARD CRITERIA
我已经在这个问题上开了一笔赏金,以便更多地接触它,并希望得到一个好的答案。我正在寻找答案:
提供一种计算/近似(大多数情况下)在tintColor
上{UINavigationBar
后创建的“内部顶部”和“内部底部”渐变颜色(参见电子表格)的RGB或HSB值的方法。 1}}。
如果您还提供了计算“返回”按钮上的“内部顶部”和“内部底部”渐变颜色的方法(类似于导航栏,但是我',我们发现这些颜色通常会略微“变暗”吗?
答案 0 :(得分:7)
简答:它不是渐变
长答案:应用色调颜色后,会在其上呈现透明的叠加图像。
它被称为:UITintedTopBarHighlight@2x.png它在UIKit艺术品中。 (上传到此处:http://cl.ly/image/2c2V3t1D1T3L)
它是2x88像素图像,必须在有色背景上水平重复。
对于后退按钮,它非常相似,但也有一个遮罩来赋予它它的形状。 UItintedBackButtonHighlight和UITintedBackButtonMask。
答案 1 :(得分:2)
很难复制确切的行为,因为Apple似乎为不同的颜色组计算不同。例如。当浅色点亮时,浅色稍微变暗。
条形按钮项目相同。对于某些颜色,普通“有边界”按钮和“完成”式按钮的区别完全不同。有时不像绿松石那样明显,但绝对可以看到橙色。
为了创建这个示例代码,我使用了PaintCode一个很好的原型btw工具。
将此代码复制到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);
}
答案 2 :(得分: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);
}
答案 3 :(得分:0)
UIButton采用单个tintColor
属性,但这并不意味着它不会计算在幕后渐变中使用的其他颜色。 Try this tutorial