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
相关产品推荐
相关产品推荐

