首页 > 解决方案 > 如何在 Swift 中将 UIColor 转换为 3/4/6/8 位十六进制字符串?

问题描述

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

我如何获得一个特定的?例如,通过调用获取“#0000FFFF”UIColor.blue.eightDigitsString

请看这个

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

标签: iosswiftuicolor

解决方案


这是一个可以提供多种格式的 hexStrings 的扩展,UIColor包括 3、4、6 和 8 位数字形式:

extension UIColor {
    enum HexFormat {
        case RGB
        case ARGB
        case RGBA
        case RRGGBB
        case AARRGGBB
        case RRGGBBAA
    }

    enum HexDigits {
        case d3, d4, d6, d8
    }

    func hexString(_ format: HexFormat = .RRGGBBAA) -> String {
        let maxi = [.RGB, .ARGB, .RGBA].contains(format) ? 16 : 256

        func toI(_ f: CGFloat) -> Int {
            return min(maxi - 1, Int(CGFloat(maxi) * f))
        }

        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0

        self.getRed(&r, green: &g, blue: &b, alpha: &a)

        let ri = toI(r)
        let gi = toI(g)
        let bi = toI(b)
        let ai = toI(a)

        switch format {
        case .RGB:       return String(format: "#%X%X%X", ri, gi, bi)
        case .ARGB:      return String(format: "#%X%X%X%X", ai, ri, gi, bi)
        case .RGBA:      return String(format: "#%X%X%X%X", ri, gi, bi, ai)
        case .RRGGBB:    return String(format: "#%02X%02X%02X", ri, gi, bi)
        case .AARRGGBB:  return String(format: "#%02X%02X%02X%02X", ai, ri, gi, bi)
        case .RRGGBBAA:  return String(format: "#%02X%02X%02X%02X", ri, gi, bi, ai)
        }
    }

    func hexString(_ digits: HexDigits) -> String {
        switch digits {
        case .d3: return hexString(.RGB)
        case .d4: return hexString(.RGBA)
        case .d6: return hexString(.RRGGBB)
        case .d8: return hexString(.RRGGBBAA)
        }
    }
}

例子

print(UIColor.red.hexString(.d3))  // #F00
print(UIColor.red.hexString(.d4))  // #F00F
print(UIColor.red.hexString(.d6))  // #FF0000
print(UIColor.red.hexString(.d8))  // #FF0000FF

print(UIColor.green.hexString(.RGB))  // #0F0
print(UIColor.green.hexString(.ARGB))  // #F0F0
print(UIColor.green.hexString(.RGBA))  // #0F0F
print(UIColor.green.hexString(.RRGGBB))  // #00FF00
print(UIColor.green.hexString(.AARRGGBB))  // #FF00FF00
print(UIColor.green.hexString(.RRGGBBAA))  // #00FF00FF

print(UIColor(red: 0.25, green: 0.5, blue: 0.75, alpha: 0.3333).hexString()) // #4080c055

推荐阅读