Android Studio中如何仅为Canvas上的PNG图标填充颜色而不修改背景
PNG图标指定色彩填充最优实现方案
问题原因
你当前的实现直接调用canvas.drawPaint(paint)会将整个Canvas对应的Bitmap区域全部填充指定颜色,完全覆盖原有PNG图标内容,因此会出现图标整体变成纯色块的异常效果。
最优实现方案
基于PorterDuff混合模式实现仅对PNG非透明区域上色,保留原图标轮廓和透明度效果,代码实现如下:
private fun tintPngIcon(imgRes: Int, targetColor: Int): BitmapDescriptor { // 加载原始PNG资源 val originalBm = BitmapFactory.decodeResource(resources, imgRes) // 按需求缩放图标尺寸 val scaledBm = Bitmap.createScaledBitmap( originalBm, (originalBm.width * 0.1).toInt(), (originalBm.height * 0.1).toInt(), true ) // 创建等尺寸的结果Bitmap val resultBm = Bitmap.createBitmap(scaledBm.width, scaledBm.height, scaledBm.config) val canvas = Canvas(resultBm) val paint = Paint() // 第一步:绘制原始缩放后的图标 canvas.drawBitmap(scaledBm, 0f, 0f, paint) // 第二步:设置颜色过滤器,SRC_IN模式仅对底层非透明区域着色 paint.colorFilter = PorterDuffColorFilter(targetColor, PorterDuff.Mode.SRC_IN) canvas.drawPaint(paint) // 回收临时Bitmap避免内存泄漏 originalBm.recycle() scaledBm.recycle() return BitmapDescriptorFactory.fromBitmap(resultBm) }
调用示例
需要填充蓝色时直接传入对应颜色参数即可:
val blueIcon = tintPngIcon(R.drawable.your_png_icon, Color.BLUE)
方案说明
- 采用
PorterDuff.Mode.SRC_IN混合模式,最终效果会保留原始PNG的透明度信息,仅将非透明区域的颜色替换为指定色彩 - 支持保留原始PNG的半透明效果,不会破坏图标原有轮廓
- 额外添加了Bitmap回收逻辑,避免不必要的内存占用
内容的提问来源于stack exchange,提问作者Dragos Ciupe
相关产品推荐
相关产品推荐

