ios 检查 UIColor 是暗还是亮?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2509443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if UIColor is dark or bright?
提问by Andre
I need to determine whether a selected UIColor (picked by the user) is dark or bright, so I can change the color of a line of text that sits on top of that color, for better readability.
我需要确定选定的 UIColor(由用户选择)是暗还是亮,因此我可以更改位于该颜色之上的一行文本的颜色,以提高可读性。
Here's an example in Flash/Actionscript (with demo): http://web.archive.org/web/20100102024448/http://theflashblog.com/?p=173
这是 Flash/Actionscript 中的一个示例(带演示):http://web.archive.org/web/20100102024448/http://theflashblog.com/?p=173
Any thoughts?
有什么想法吗?
Cheers, Andre
干杯,安德烈
UPDATE
更新
Thanks to everyone's suggestions, here's the working code:
感谢大家的建议,这是工作代码:
- (void) updateColor:(UIColor *) newColor
{
const CGFloat *componentColors = CGColorGetComponents(newColor.CGColor);
CGFloat colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
if (colorBrightness < 0.5)
{
NSLog(@"my color is dark");
}
else
{
NSLog(@"my color is light");
}
}
Thanks once again :)
再次感谢 :)
采纳答案by Erik Nedwidek
W3C has the following: http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
W3C 有以下内容:http: //www.w3.org/WAI/ER/WD-AERT/#color-contrast
If you're only doing black or white text, use the color brightness calculation above. If it is below 125, use white text. If it is 125 or above, use black text.
如果您只处理黑色或白色文本,请使用上面的颜色亮度计算。如果低于 125,请使用白色文本。如果是 125 或以上,请使用黑色文本。
edit 1: bias towards black text. :)
编辑 1:偏向黑色文本。:)
edit 2: The formula to use is ((Red value * 299) + (Green value * 587) + (Blue value * 114)) / 1000.
编辑2:使用的公式是((红色值* 299)+(绿色值* 587)+(蓝色值* 114))/ 1000。
回答by josh-fuggle
Here is a Swift (3) extension to perform this check.
这是执行此检查的 Swift (3) 扩展。
This extension works with greyscale colors. However, if you are creating all your colors with the RGB initializer and not using the built in colors such as UIColor.black
and UIColor.white
, then possibly you can remove the additional checks.
此扩展程序适用于灰度颜色。但是,如果要创建与RGB初始化所有的颜色,而不是使用内置的颜色,如UIColor.black
和UIColor.white
,然后可能你可以删除额外的检查。
extension UIColor {
// Check if the color is light or dark, as defined by the injected lightness threshold.
// Some people report that 0.7 is best. I suggest to find out for yourself.
// A nil value is returned if the lightness couldn't be determined.
func isLight(threshold: Float = 0.5) -> Bool? {
let originalCGColor = self.cgColor
// Now we need to convert it to the RGB colorspace. UIColor.white / UIColor.black are greyscale and not RGB.
// If you don't do this then you will crash when accessing components index 2 below when evaluating greyscale colors.
let RGBCGColor = originalCGColor.converted(to: CGColorSpaceCreateDeviceRGB(), intent: .defaultIntent, options: nil)
guard let components = RGBCGColor?.components else {
return nil
}
guard components.count >= 3 else {
return nil
}
let brightness = Float(((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000)
return (brightness > threshold)
}
}
Tests:
测试:
func testItWorks() {
XCTAssertTrue(UIColor.yellow.isLight()!, "Yellow is LIGHT")
XCTAssertFalse(UIColor.black.isLight()!, "Black is DARK")
XCTAssertTrue(UIColor.white.isLight()!, "White is LIGHT")
XCTAssertFalse(UIColor.red.isLight()!, "Red is DARK")
}
Note: Updated to Swift 3 12/7/18
注意:更新到 Swift 3 12/7/18
回答by Remy Vanherweghem
Using Erik Nedwidek's answer, I came up with that little snippet of code for easy inclusion.
使用 Erik Nedwidek 的回答,我想出了一小段代码以便于包含。
- (UIColor *)readableForegroundColorForBackgroundColor:(UIColor*)backgroundColor {
size_t count = CGColorGetNumberOfComponents(backgroundColor.CGColor);
const CGFloat *componentColors = CGColorGetComponents(backgroundColor.CGColor);
CGFloat darknessScore = 0;
if (count == 2) {
darknessScore = (((componentColors[0]*255) * 299) + ((componentColors[0]*255) * 587) + ((componentColors[0]*255) * 114)) / 1000;
} else if (count == 4) {
darknessScore = (((componentColors[0]*255) * 299) + ((componentColors[1]*255) * 587) + ((componentColors[2]*255) * 114)) / 1000;
}
if (darknessScore >= 125) {
return [UIColor blackColor];
}
return [UIColor whiteColor];
}
回答by neoneye
Swift3
斯威夫特3
extension UIColor {
var isLight: Bool {
var white: CGFloat = 0
getWhite(&white, alpha: nil)
return white > 0.5
}
}
// Usage
if color.isLight {
label.textColor = UIColor.black
} else {
label.textColor = UIColor.white
}
回答by mattsven
My solution to this problem in a category (drawn from other answers here). Also works with grayscale colors, which at the time of writing none of the other answers do.
我在一个类别中对这个问题的解决方案(从这里的其他答案中提取)。也适用于灰度颜色,在撰写本文时,其他答案都没有。
@interface UIColor (Ext)
- (BOOL) colorIsLight;
@end
@implementation UIColor (Ext)
- (BOOL) colorIsLight {
CGFloat colorBrightness = 0;
CGColorSpaceRef colorSpace = CGColorGetColorSpace(self.CGColor);
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
if(colorSpaceModel == kCGColorSpaceModelRGB){
const CGFloat *componentColors = CGColorGetComponents(self.CGColor);
colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
} else {
[self getWhite:&colorBrightness alpha:0];
}
return (colorBrightness >= .5f);
}
@end
回答by Kaiyuan Xu
Swift 4 Version
斯威夫特 4 版本
extension UIColor {
func isLight() -> Bool {
guard let components = cgColor.components, components.count > 2 else {return false}
let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000
return (brightness > 0.5)
}
}
回答by Sunkas
Simpler Swift 3 extension:
更简单的 Swift 3 扩展:
extension UIColor {
func isLight() -> Bool {
guard let components = cgColor.components else { return false }
let redBrightness = components[0] * 299
let greenBrightness = components[1] * 587
let blueBrightness = components[2] * 114
let brightness = (redBrightness + greenBrightness + blueBrightness) / 1000
return brightness > 0.5
}
}
回答by kakilangit
If you prefer the block version:
如果您更喜欢块版本:
BOOL (^isDark)(UIColor *) = ^(UIColor *color){
const CGFloat *component = CGColorGetComponents(color.CGColor);
CGFloat brightness = ((component[0] * 299) + (component[1] * 587) + (component[2] * 114)) / 1000;
if (brightness < 0.75)
return YES;
return NO;
};
回答by Lucho
For me using only CGColorGetComponents didn't worked, I get 2 components for UIColors like white. So I have to check the color spaceModel first. This is what I came up with that ended up being the swift version of @mattsven's answer.
对我来说,只使用 CGColorGetComponents 没有用,我得到了 2 个 UIColors 组件,比如白色。所以我必须先检查颜色空间模型。这就是我想出的,最终成为@mattsven 答案的快速版本。
Color space taken from here: https://stackoverflow.com/a/16981916/4905076
从这里获取的色彩空间:https: //stackoverflow.com/a/16981916/4905076
extension UIColor {
func isLight() -> Bool {
if let colorSpace = self.cgColor.colorSpace {
if colorSpace.model == .rgb {
guard let components = cgColor.components, components.count > 2 else {return false}
let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000
return (brightness > 0.5)
}
else {
var white : CGFloat = 0.0
self.getWhite(&white, alpha: nil)
return white >= 0.5
}
}
return false
}
回答by Cuddy
UIColor has the following method to convert to HSB color space:
UIColor 有以下方法可以转换为HSB 颜色空间:
- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha;