在 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> = CenterCrop 或 FitCenter
即使我没有调用 .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)影响下一次加载图像的结果。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917874/viewspace-3086073/ ,如需转载,请注明出处,否则将追究法律责任。