如何在Swift中将UIColor转换为3/4/6/8位十六进制字符串?

时间:2018-05-10 02:28:26

标签: ios swift uicolor

如何在Swift中将UIColor转换为3/4/6/8位的十六进制字符串?

我如何得到一个特殊的?例如,get"#0000FFFF"致电UIColor.blue.eightDigitsString

请参阅this

  

5.2。 RGB十六进制表示法:#RRGGBB

     

CSS十六进制颜色表示法允许通过将通道指定为十六进制数来指定颜色,这类似于通常直接在计算机代码中编写颜色的方式。它也比用rgb()表示法写出相同的颜色要短。

     

a的语法是< hash-token>其值由3个,4个,6个或8个十六进制数组成的标记。换句话说,十六进制颜色被写为哈希字符,"#",后跟一些数字0-9或字母af(字母的大小写无关紧要 - #00ff00是与#00FF00相同。

     

给定的十六进制数字数决定了如何将十六进制表示法解码为RGB颜色:

     

6位数   第一对数字,解释为十六进制数,指定颜色的红色通道,其中00表示最小值,ff(十进制255)表示最大值。以相同方式解释的下一对数字指定绿色通道,最后一对指定蓝色。颜色的alpha通道完全不透明。   换句话说,#00ff00表示与rgb(0 255 0)(柠檬绿)相同的颜色。

     

8位数   前6位数字的解释与6位数字符号相同。最后一对数字,解释为十六进制数字,指定颜色的alpha通道,其中00表示完全透明的颜色,ff表示完全不透明的颜色。   换句话说,#0000ffcc表示与rgb(0 0 100%/ 80%)(略微透明的蓝色)相同的颜色。

     

3位数   这是6位数表示法的较短变体。第一个数字,解释为十六进制数,指定颜色的红色通道,其中0表示最小值,f表示最大值。接下来的两个数字分别以相同的方式表示绿色和蓝色通道。颜色的alpha通道完全不透明。   这种语法经常被解释为说它与通过"复制"获得的6位数表示法相同。所有的数字。例如,符号#123指定与符号#112233相同的颜色。这种指定颜色的方法具有较低的分辨率"而不是6位数的表示法;在3位十六进制语法中只有4096种可能的颜色,而在6位十六进制语法中则只有大约1700万种。

     

4位数   这是8位数字符号的较短变体,"扩展"与3位数表示法相同。第一个数字,解释为十六进制数,指定颜色的红色通道,其中0表示最小值,f表示最大值。接下来的三个数字分别代表绿色,蓝色和alpha通道。

现在我已经知道如何将UIColor对象转换为6位十六进制字符串。但我不确定如何将其转换为3位/ 4位/ 8位十六进制字符串以及应该注意的内容。

guard let components = cgColor.components, components.count >= 3 else {
    return nil
}
let r = Float(components[0])
let g = Float(components[1])
let b = Float(components[2])
var a = Float(1.0)
if components.count >= 4 {
    a = Float(components[3])
}
if alpha {
    // rrggbbaa mode
    // is there any difference between rrggbbaa and aarrggbb?
    return String(format: "%02lX%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255), lroundf(a * 255))
} else {
    // rrggbb mode
    return String(format: "%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255))
}

注意:它UIColor为字符串,而非字符串为UIColor

1 个答案:

答案 0 :(得分:0)

任何UIColor实例都可以用8个十六进制数字表示:例如#336699CC。对于某些颜色,可以使用较短的表示:

  • 对于不透明的颜色(alpha未指定或1.0),可以不使用alpha组件:#336699FF变为#336699
  • 如果所有颜色组件由同一个数字对组成,则只需指定一次数字:#336699CC变为#369C,但#335799CC不能缩短
  • 可以合并上述两条规则:#336699FF变为#369

以下函数将返回给定UIColor允许的最短有效表示。

struct HexRepresentationOptions: OptionSet {
    let rawValue: UInt

    static let allowImplicitAlpha = HexRepresentationOptions(rawValue: 1 << 0)
    static let allowShortForm = HexRepresentationOptions(rawValue: 1 << 1)

    static let allowAll: HexRepresentationOptions = [
        .allowImplicitAlpha, 
        .allowShortForm
    ]
}

func hexRepresentation(forColor color: UIColor, 
                       options: HexRepresentationOptions = .allowAll) -> String? {
    var red: CGFloat = 0.0
    var green: CGFloat = 0.0
    var blue: CGFloat = 0.0
    var alpha: CGFloat = 0.0

    guard color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
        return nil
    }

    let colorComponents: [CGFloat]
    if options.contains(.allowImplicitAlpha) && alpha == 1.0 {
        colorComponents = [red, green, blue]
    } else {
        colorComponents = [red, green, blue, alpha]
    }

    let hexComponents = colorComponents.map { component -> (UInt8, UInt8, UInt8) in
        let hex = UInt8(component * 0xFF)
        return (hex, hex & 0x0F, hex >> 4)
    }

    let hasAlpha = colorComponents.count == 4
    let useShortForm = options.contains(.allowShortForm) && 
        !hexComponents.contains(where: { c in c.1 != c.2 })

    let hexColor: UInt64 = hexComponents.reduce(UInt64(0)) { result, component in
        if useShortForm {
            return (result << 4) | UInt64(component.1)
        } else {
            return (result << 8) | UInt64(component.0)
        }
    }

    switch (useShortForm, hasAlpha) {
    case (true, false):
        return String(format: "#%03X", hexColor)
    case (true, true):
        return String(format: "#%04X", hexColor)
    case (false, false):
        return String(format: "#%06X", hexColor)
    case (false, true):
        return String(format: "#%08X", hexColor)
    }
}