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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:06:04