You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中用Coil加载SVG时出现display-p3颜色关键字错误

Coil加载含display-p3颜色的SVG图片失败问题解决

我用Coil结合Jetpack Compose加载SVG图片时,部分图片加载正常,部分直接失败。查日志发现,失败的图片都用了color(display-p3 ...)格式的颜色,日志里全是“Invalid colour keyword: color(display-p3 ...)”的错误。

加载图片的相关代码

@Composable
fun coilPainter(
    imageUrl: Any?,
    scale: Scale = Scale.FIT,
    size: Size = Size.ORIGINAL,
): AsyncImagePainter = rememberAsyncImagePainter(
    model = ImageRequest.Builder(LocalContext.current)
        .data(imageUrl)
        .decoderFactory(SvgDecoder.Factory()) // 使用SvgDecoder支持SVG
        .crossfade(true)
        .size(size)
        .scale(scale)
        .diskCachePolicy(CachePolicy.ENABLED)
        .build(),
)

@Composable
fun ImageProfileLoader(
    image: Any? = null,
    text: String? = null,
    isDefaultBankIcon: Boolean = false,
    backgroundColor: Color = Color.Gray,
    size: Dp = 55.dp,
    fontSize: Dp = 16.dp,
) {
    val painter = coilPainter(imageUrl = image)

    Box(
        modifier = Modifier
            .size(size)
            .background(backgroundColor, shape = CircleShape)
            .clip(CircleShape),
        contentAlignment = Alignment.Center
    ) {
        if (painter.state is AsyncImagePainter.State.Error) {
            if (text?.isEmpty() == true) {
                Image(
                    modifier = Modifier.fillMaxSize(),
                    painter = painterResource(R.drawable.default_image_profile).takeIf { !isDefaultBankIcon } ?: painterResource(R.drawable.default_bank_icon),
                    contentDescription = "",
                    contentScale = ContentScale.Crop
                )
            } else {
                TextCustom(
                    text = text?.first()?.uppercaseChar().toString(),
                    fontSize = fontSize,
                    color = Color171717
                )
            }
        }

        if (painter.state is AsyncImagePainter.State.Success) {
            Image(
                modifier = Modifier.fillMaxSize(),
                painter = painter,
                contentDescription = "",
                contentScale = ContentScale.Crop
            )
        }

        if (painter.state is AsyncImagePainter.State.Loading) {
            Spacer(
                modifier = Modifier
                    .size(size)
                    .clip(CircleShape)
                    .shimmerEffect()
            )
        }
    }
}

错误日志

Invalid colour keyword: color(display-p3 0.0000 0.6980 0.9137)
Invalid colour keyword: color(display-p3 0.0000 0.5922 0.8392)
Invalid colour keyword: color(display-p3 0.0000 0.5725 0.8275)
Invalid colour keyword: color(display-p3 0.0000 0.4980 0.7686)
Invalid colour keyword: color(display-p3 0.0000 0.4392 0.7294)
Invalid colour keyword: color(display-p3 0.0000 0.4078 0.7059)
Invalid colour keyword: color(display-p3 0.0000 0.4000 0.7020)
Invalid colour keyword: color(display-p3 0.0000 0.4000 0.7020)
Invalid colour keyword: color(display-p3 0.9490 0.8941 0.8039)
Invalid colour keyword: color(display-p3 0.8745 0.7294 0.5020)
Invalid colour keyword: color(display-p3 0.8275 0.6275 0.3098)
Invalid colour keyword: color(display-p3 0.8118 0.5882 0.2392)

解决方案

1. 自定义SVG解码器处理display-p3颜色

Coil默认的SvgDecoder依赖的AndroidSVG库不支持display-p3格式,我们可以自定义解码器,先把SVG里的display-p3颜色转换成普通RGB格式再解码:

class CustomSvgDecoder(private val context: Context) : Decoder {
    override fun handles(data: DataSource, options: Options): Boolean {
        // 和默认SvgDecoder一样判断是否处理SVG
        return SvgDecoder.Factory().handles(data, options)
    }

    override suspend fun decode(data: DataSource, options: Options): DecodeResult {
        // 读取SVG内容
        val svgContent = data.source().readUtf8()
        // 替换display-p3颜色为RGB十六进制值
        val processedContent = svgContent.replace(Regex("color\\(display-p3 (\\d+\\.\\d+) (\\d+\\.\\d+) (\\d+\\.\\d+)\\)")) { match ->
            val r = (match.groupValues[1].toFloat() * 255).toInt()
            val g = (match.groupValues[2].toFloat() * 255).toInt()
            val b = (match.groupValues[3].toFloat() * 255).toInt()
            "#%02X%02X%02X".format(r, g, b)
        }
        // 把处理后的内容转成输入流
        val inputStream = processedContent.byteInputStream()
        val svg = SVG.getFromInputStream(inputStream)
        // 绘制到Bitmap,和默认解码逻辑一致
        val bitmapSize = options.size.run { Size(width, height) }
        val bitmap = Bitmap.createBitmap(bitmapSize.width.toInt(), bitmapSize.height.toInt(), Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        svg.renderToCanvas(canvas)
        return DecodeResult.Source(bitmap)
    }

    class Factory : Decoder.Factory {
        override fun create(context: Context, options: Options): Decoder {
            return CustomSvgDecoder(context)
        }
    }
}

然后在coilPainter里替换解码器:

.decoderFactory(CustomSvgDecoder.Factory())

2. 预处理SVG源文件

如果能修改SVG文件,直接把所有color(display-p3 r g b)替换成对应的RGB十六进制值(比如color(display-p3 0 0.698 0.9137)转成#00B1E9),这样默认解码器就能正常识别。

3. 升级依赖库

检查AndroidSVG的最新版本,看是否已经支持display-p3颜色。如果支持,直接升级Coil的svg扩展依赖到对应版本,不用改代码就能解决问题。


内容的提问来源于stack exchange,提问作者LORS HIM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:04:53