使用Jetpack Compose从十六进制字符串获取颜色

66
如何在Jetpack Compose的Color类中解析十六进制字符串(例如#9CCC65)。

P.S:在Jetpack Compose包中,选项似乎已经消失了。


当前解决方法: 从标准的Color类中导出parseColor()方法。

@ColorInt
fun parseColor(@Size(min = 1) colorString: String): Int {
    if (colorString[0] == '#') { // Use a long to avoid rollovers on #ffXXXXXX
        var color = colorString.substring(1).toLong(16)
        if (colorString.length == 7) { // Set the alpha value
            color = color or -0x1000000
        } else require(colorString.length == 9) { "Unknown color" }
        return color.toInt()
    }
    throw IllegalArgumentException("Unknown color")
}

6
将十六进制字符串解析为 Long 类型,然后将该 Long 值传递给 Color() 函数。 - CommonsWare
@CommonsWare 尝试从标准 Color 类中导出 parseColor() 方法。虽然目前它能正常工作,但我认为 Jetpack Compose 团队应该添加这个方法。 - Vipul Asri
@CommonsWare 我也尝试了你的解决方案,但是出现了 java.lang.NumberFormatException 异常。 - Vipul Asri
如果您尝试解析“#9CCC65”,那将不起作用,因为“#”不是数字的一部分。算法与parseColor()中所见几乎相同。如果Compose团队添加了对此类颜色字符串的支持,我不会争论,但如果他们决定这超出了范围并且可以被应用程序或其他非Compose库轻松处理,我也不会感到惊讶。 - CommonsWare
@CommonsWare 是的,我明白你的意思。谢谢! - Vipul Asri
8个回答

95

将传递方式从字符串改为十六进制。例如,如果您想要这个#9CCC65颜色,只需删除前面的#并用0xFF替换它。例如:

val PrimaryBlue = Color(0xFF9CCC65)

18
这个回答与问题不相关,因为问题明确要求在运行时将字符串解析为颜色。 - Vipul Asri
1
抱歉,我没有看到任何地方需要在运行时解析。 - Mayank Wadhwa
6
这个答案是最好的,因为我正在寻找这个解决方案,而且我第一次来到了这个问题。 - mama
我花了太长时间才意识到我添加的是0x而不是0xff....大家不要像我一样。 - JBest
有一个答案,这是对一个更好表达的问题的答案,就是它!谢谢 @MayankWadhwa - Joshua Kusaasira
@MayankWadhwa 谢谢你的回答,真是救了我的一天。 - Edson Dias

59
你可以使用这个对象类来调用getColor方法。
object HexToJetpackColor {
    fun getColor(colorString: String): Color {
            return Color(android.graphics.Color.parseColor("#" + colorString))
    }
}

或者我们可以使用一个扩展函数。
fun Color.Companion.fromHex(colorString: String) = Color(android.graphics.Color.parseColor("#" + colorString))

Jetpack的Color类,即`androidx.ui.graphics.Color`,在构造函数中只接受RGB、ARGB、ColorSpace和colorInt。请参见:`Color.kt`。
因此,在这里我们直接访问`android.graphics.Color`中的`parseColor()`方法,该方法返回colorInt。
因此,可以使用parseColor()方法获取colorInt,然后将其提供给Jetpack的Color类以获取`androidx.ui.graphics.Color`对象。

4
也许你可以在你的项目中添加一个扩展函数。fun Color.fromHex(color: String) = Color(android.graphics.Color.parseColor("#" + colorString)) - facundomr
2
@facundomr 好的,你应该使用Color.Companion而不是仅仅使用Color,这样可以在Color.fromString()中使用它。 - Tura

21

Int.dp 类似,也可以有 String.color 扩展属性。

val String.color 
    get() = Color(android.graphics.Color.parseColor(this))

这可以用作颜色十六进制字符串的成员属性。

"#FF0000".color

15

我之前也遇到了这个问题,最终找到了解决方案:

    val myColorString = "#B00020"
    val myComposeColorInt = Color(myColorString.toColorInt())

工作和简单的解决方案 - Chuka_FC
2
只是一点提示:toColorInt() 在底层调用了 android.graphics.Color.parseColor(),因此无法在常规单元测试中使用。 - Bartek

13

将十六进制字符串转换为颜色 [此扩展函数可在 Android SDK 中使用]

Color("#FFFFFF".toColorInt())

如果需要将其转换回十六进制代码

fun Color.toHexCode(): String {
    val red = this.red * 255
    val green = this.green * 255
    val blue = this.blue * 255
    return String.format("#%02x%02x%02x", red.toInt(), green.toInt(), blue.toInt())
}

如果您还需要 alpha 值

fun Color.toHexCodeWithAlpha(): String {
            val alpha = this.alpha*255
            val red = this.red * 255
            val green = this.green * 255
            val blue = this.blue * 255
            return String.format("#%02x%02x%02x%02x", alpha.toInt(),red.toInt(), green.toInt(), blue.toInt())
        }

12

有没有不依赖于Android的解决方案?#KMP

val hashColorString = "#00AB18"
val color = Color(hashColorString.removePrefix("#").toLong(16) or 0x00000000FF000000)

这个不起作用。尝试使用“#FFFFFF”,你将得不到白色。 - Bartek
你是对的。我已经修复了 :) - Majkeee

12

另一个选项是编写类似于android.graphics.Color的扩展函数:

import androidx.compose.ui.graphics.Color

fun Color.Companion.parse(colorString: String): Color =
    Color(color = android.graphics.Color.parseColor(colorString))

然后你可以像这样编写你的compose:

Modifier.background(Color.parse("#FF0000"))

1
在我看来,这种方式在语法上是最有意义的。 - Brandon McAnsh

2
如果你不想导入 android.graphics.Color,这里有另一个简单的替代方案:
val hexString = "#f8f8f2"
Color(("ff" + hexString.removePrefix("#").lowercase()).toLong(16))

在这种情况下,Color 将立即是 androidx.compose.ui.graphics.Color 中的颜色。

这个不起作用。尝试使用“#ffffff”,你将得不到白色。 - Bartek
我刚刚尝试了ffffff#ffffff,它们都可以正常工作,@Bartek。白色被显示出来了。这是我正在运行的确切代码:fun hexToColor(hexString: String): Color { return Color(("ff" + hexString.removePrefix("#").lowercase()).toLong(16)) }你确定你在代码的其他地方没有犯错吗? - haikalpribadi
答案已经修复,现在它可以正常工作了。 - Bartek
它正在工作。谢谢! - NightFury

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接