【踩坑记录】Glide 抹掉图片圆角透明区域的隐藏机制:一次 Alpha 通道的消失之谜

149 阅读3分钟

前言:

原以为只是个图片加载问题,结果绕了一圈,发现是 Glide、Bitmap、View 三者联动下的隐秘 Bug。这是一篇关于图片透明圆角被“吃掉”的终极分析与解决方案。

背景描述:透明圆角图片失效的奇怪现象

在 Android 项目中,我们有一张设计师提供的 PNG 图片,带有透明圆角(四角透明,非遮罩绘制)。在 ImageView 中直接设置资源或 Glide 加载该图片时,出现了神奇的现象:

直接设置: imageView.setImageResource(R.drawable.xxx) → 显示正常,圆角透明区域完整;

Glide 加载: Glide.with(...).load(...).into(imageView) → 某些设备或首次加载时,圆角消失,变成实心矩形。

更奇怪的是,加载一张其他尺寸图片后再加载原图,圆角又出现了……

图片

原因分析:Glide 的默认 Bitmap 操作会“硬编码”处理 Alpha

核心问题:Glide 默认会对 Bitmap 进行一次“隐式转换”,影响透明区域,即使我没有手动调用 .transform(),Glide 仍然默认执行了一系列与尺寸、格式和缓存相关的 Transformation,其中包括:

  • 硬编码 bitmap config 为 RGB_565 或 ARGB_8888
  • Bitmap 可能未设置 hasAlpha = true
  • 默认使用 BitmapPool,复用带错状态的 Bitmap

这种默认行为在某些场景中会抹掉 alpha 通道,导致圆角透明部分直接显示为实色。

关键源码分析:默认 Transformation 怎么影响透明通道?

我们从 Glide 的 BitmapDrawableTranscoder、Downsampler 和 DecodeJob 入手。

  1. Glide 加载流程核心链路(简化版)
ModelLoader → Decoder → Downsampler → BitmapPool → Transformation → Target

其中,默认路径会走:

Transformation<Bitmap= CenterCropFitCenter

即使我没有调用 .transform(...),Glide 默认依然会套用一种尺寸适配策略,而这些 Transformation 最终会调用:

Bitmap result = bitmapPool.get(..., Bitmap.Config.ARGB_8888);
result.setHasAlpha(false); // 或未设置,默认是 false!

于是就有:

  • 原图带透明;

  • 结果 Bitmap 不支持透明;

  • 合成图时透明区域被填色(通常是黑或白),圆角失效。

实验一下:默认行为是如何“吃掉”圆角的?

Glide.with(context)
    .load(R.drawable.rounded_image) // 这是透明圆角 PNG
    .into(imageView)
  • 圆角 正常情况:直接使用 setImageResource,或自定义BitmapFactory 解码(保留透明)
  • 圆角 被抹掉情况:使用 Glide 默认加载逻辑(无 .transform())

加入 .dontTransform() 后:

Glide.with(context)
    .load(R.drawable.rounded_image)
    .dontTransform()
    .into(imageView)

圆角恢复解决方案:明确关闭默认 Transform

Glide.with(context)
    .load(imageUrl)
    .dontTransform()  // 关闭默认 CenterCrop/FitCenter 等 transform
    .format(DecodeFormat.PREFER_ARGB_8888) // 强制启用透明支持
    .into(imageView)

当然也可以加上以下操作,组成防御性编程,防止使用 BitmapPool 中可能“污染过”的旧 Bitmap。

.skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE)

 延伸分析:为啥小图 -> 大图能恢复圆角?问题找到了之后,就有个问题,为什么切换不同尺寸的图片之后,圆角就会出现呢?

背后原因是:

  • 小图尺寸不匹配 Glide 的缓存条件,触发重新解码

  • 可能跳过了默认的 Transform 流程(或 BitmapPool 无可复用项)

  • 重新创建了支持透明的 Bitmap

这个现象正好印证了:BitmapPool 的状态(如 hasAlpha)影响下一次加载图像的结果。

这类“隐形 Bug”最可怕的是:它不是代码出错,而是框架默认逻辑与我们的的预期发生偏差。在实际开发中,多理解像 Glide 这样的图片库内部机制,能规避很多非显性问题。