背景
在需求开发中,经常会遇到需要展示图片列表的情况。然而,由于网络问题、图片链接失效等原因,某些图片可能无法正常加载。为了优化用户体验,通常会为加载失败的图片提供一个默认的占位图。
在常规的实现方式中,可能会直接使用一张默认图片来作为占位图(如果是个单色图,可以直接用一个drawable文件)。然而,如果图片列表里每个Item宽高比都是变化的时候,默认图片会因为宽高比不同而导致变形,虽然可以通过 ImageView 的 scaleType 设置 CENTER_CROP 以适应不同的图片比例不变形,但如果默认图片本身包含一个居中的小图标,在不同的宽高比下,小图标的显示效果可能会变形或错位。
问题分析
假设我们的默认错误图片是如下所示的样式(背景色 + 一个居中的错误图标):
如果我们将其合成一张完整的 PNG 图片并使用 CENTER_CROP 适配不同的 ImageView 尺寸,可能会遇到两个问题: 1. 小图标会跟随图片裁剪,可能会放大、变形,导致显示不一致。 2. 不同比例的 ImageView 会截取不同区域,导致小图标的位置和大小不可控。
为了解决这个问题,可以换一种思路,利用 layer-list 来动态组合背景和图标,从而确保小图标始终保持固定大小和居中位置。
解决方案:使用 layer-list
在 drawable 资源中,layer-list 允许我们叠加多个图层,可以将背景和图标分开定义,保证不同尺寸的 ImageView 显示时,背景始终铺满,而小图标始终居中,且不会因裁剪而变形。其中小图片的资源如下:

- 创建 layer-list 资源文件
在 res/drawable/ 目录下创建 drawable_default_error.xml:
kotlin
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 背景矩形 -->
<item>
<shape android:shape="rectangle">
<solid android:color="@color/gray_normal" /> <!-- 设置背景颜色 -->
</shape>
</item>
<!-- 居中的错误图标 -->
<item
android:width="60dp"
android:height="60dp"
android:gravity="center">
<bitmap
android:gravity="center"
android:src="@drawable/chat_ask_message_error" />
</item>
</layer-list>
- 代码中使用 layer-list
在使用 Glide 或其他图片加载框架时,我们可以直接将 drawable_default_error.xml 作为 placeholder 和 error 资源:
kotlin
Glide.with(activity)
.load(url)
.placeholder(R.drawable.drawable_default_error) // 加载中显示的占位图
.error(R.drawable.drawable_default_error) // 加载失败时显示的默认图
.into(imageView)
效果展示
当图片加载失败时,ImageView 会显示 drawable_default_error.xml 组合的背景 + 图标,效果如下:

相比直接使用一张完整的 PNG 图片,layer-list 方案的优点:
- 保证背景始终填充整个 ImageView,不会因为 scaleType 而变形。
- 小图标始终保持固定大小,居中不变形,适应不同的 ImageView 尺寸。
- 支持动态调整背景色或小图标,无需重新制作整张图片,维护更方便。
总结
在 Android 开发中,layer-list 是一个非常实用的 Drawable 资源,它可以将多个层叠的图形、颜色、图片等组合在一起,实现复杂的视觉效果。在需要为加载失败的图片提供占位图时,使用 layer-list 可以保证背景填充、图标居中且不会变形。