iOS开发中带透明度的8位Hex颜色码解析结果不符合预期
问题根因
8位带透明度的Hex色值存在两种通用通道排列规范,当前代码的解析顺序和传入色值遵循的顺序不匹配,四个颜色分量全部错位:
- 传入的色值
#80478295遵循AARRGGBB排列规范:前2位为Alpha透明度通道,后续6位依次为R、G、B颜色通道,对应分量为A=0x80(对应50%透明度)、R=0x47、G=0x82、B=0x95,和预期RGBA值完全吻合 - 当前代码的解析逻辑按RRGGBBAA排列实现:将前2位解析为R通道,后续依次解析G、B通道,最后2位解析为Alpha通道,直接导致原本属于Alpha通道的0x80被读为R值,原R值0x47被读为G值,原G值0x82被读为B值,原B值0x95被读为Alpha值,和实际打印出的错误分量完全匹配。
修复方案
调整8位Hex的通道取值位运算逻辑,匹配AARRGGBB排列规则,同时可兼容6位无透明度的常规Hex色值,修正后代码如下:
public convenience init?(hex: String) { let r, g, b, a: CGFloat if hex.hasPrefix("#") { let start = hex.index(hex.startIndex, offsetBy: 1) let hexColor = String(hex[start...]) var hexNumber: UInt64 = 0 guard Scanner(string: hexColor).scanHexInt64(&hexNumber) else { return nil } if hexColor.count == 8 { // 8位AARRGGBB格式解析 a = CGFloat((hexNumber & 0xff000000) >> 24) / 255 r = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 g = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 b = CGFloat(hexNumber & 0x000000ff) / 255 self.init(red: r, green: g, blue: b, alpha: a) return } else if hexColor.count == 6 { // 兼容6位RRGGBB无透明度格式,默认不透明 r = CGFloat((hexNumber & 0xff0000) >> 16) / 255 g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255 b = CGFloat(hexNumber & 0x0000ff) / 255 self.init(red: r, green: g, blue: b, alpha: 1) return } } return nil }
使用修正后代码解析#80478295,得到的分量为R≈0.278、G≈0.510、B≈0.584、A≈0.502,和预期值的微小差异为浮点计算精度误差,显示效果完全符合要求。
内容的提问来源于stack exchange,提问作者venky
相关产品推荐
相关产品推荐

