你真的了解 Android Drawable 吗?这 15 种 Drawable,第 7 种救了我整个项目!

avatar
莫雨IP属地:上海
02026-01-29:20:01:04字数 4902阅读 0

“一个 Drawable 用得好,胜过十行自定义 View”
—— 某位深夜改需求的 Android 老兵


🌟 开场白:你以为 Drawable 只是“图片”?

“把这张图设为按钮背景”——这是新手对 Drawable 的初印象。
但资深开发者知道:Drawable 是 Android UI 的“隐形骨架”
从水波纹反馈到动态进度条,从状态切换到内存优化,它默默撑起 80% 的视觉体验。

今天,我们抛开“Drawable=图片”的刻板印象,带你系统梳理 Android Drawable 家族全图谱!文末附 实战避坑指南+性能优化清单,建议收藏⭐


📚 Drawable 家族全景图(附使用场景+代码片段)

🔷 基础图像类

类型核心能力典型场景一句话提示
BitmapDrawable封装 PNG/JPEG 等位图App 图标、背景图注意内存!大图用 inSampleSize 压缩
NinePatchDrawable.9.png 可拉伸区域定义聊天气泡、按钮背景拉伸区/内容区标记得精准,否则变形
VectorDrawableXML 矢量图(无限缩放)Material Design 图标低版本用 app:srcCompat + Support Library
<!-- vector 示例:心形图标 -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FF0000"
        android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5C2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
</vector>

🔷 形状与色彩类

类型核心能力典型场景高频技巧
GradientDrawableXML 定义形状+渐变(<shape>圆角按钮、进度条底android:useLevel="false" 避免被当 LevelList 用
ColorDrawable纯色填充临时占位背景、分割线new ColorDrawable(Color.TRANSPARENT) 快速清背景
<!-- 渐变圆角按钮 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#FF6B6B"
        android:endColor="#4ECDC4"
        android:angle="135"/>
    <corners android:radius="12dp"/>
    <padding android:left="16dp" android:top="8dp"/>
</shape>

🔷 状态与组合类(🔥 高频考点!)

类型核心能力典型场景血泪教训
StateListDrawable按 View 状态切换(<selector>按钮按下/禁用效果item 顺序决定优先级! 默认状态放最后
LayerDrawable多 Drawable 叠加(<layer-list>带边框头像、徽章android:gravity 精准定位子层
LevelListDrawable按 level 值切换(如电量/信号)电量图标、评分星级drawable.setLevel(5000) 动态控制
<!-- 按钮状态选择器(正确顺序!) -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:drawable="@color/gray"/>
    <item android:state_pressed="true" android:drawable="@color/blue_dark"/>
    <item android:drawable="@color/blue"/> <!-- 默认状态必须放最后! -->
</selector>

🔷 动效与变换类

类型核心能力典型场景注意事项
AnimationDrawable帧动画(<animation-list>加载动画、表情动图start() 必须在 View 可见后调用
TransitionDrawable两 Drawable 淡入淡出刷新指示器、主题切换startTransition(300) 控制时长
RippleDrawable水波纹反馈(API 21+)Material 按钮点击效果低版本用 ?attr/selectableItemBackground 兼容
<!-- 水波纹(带边界) -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <corners android:radius="8dp"/>
            <solid android:color="@android:color/white"/>
        </shape>
    </item>
</ripple>

🔷 进阶工具类

类型用途实战价值
InsetDrawable内边距包裹(替代 padding)精确控制 Drawable 显示区域
ClipDrawable按 level 裁剪(进度条核心)自定义水平/圆形进度条
RotateDrawable旋转动画音乐播放旋转图标
ScaleDrawable按 level 缩放动态调整图标大小

💡 高阶技巧:这些用法让面试官眼前一亮

✅ 技巧1:用 LayerDrawable 实现“带红点的头像”

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/avatar"/>
    <item android:right="8dp" android:top="8dp">
        <shape android:shape="oval">
            <solid android:color="#FF0000"/>
            <size android:width="12dp" android:height="12dp"/>
        </shape>
    </item>
</layer-list>

✅ 技巧2:ClipDrawable 手写进度条(零 View 代码!)

ClipDrawable clip = (ClipDrawable) progressBar.getBackground();
clip.setLevel((int)(progress * 10000)); // level 范围 0~10000

✅ 技巧3:VectorDrawable + AnimatedVectorDrawable = 交互动效

(配合 Shape Shifter 工具生成路径动画,实现“播放→暂停”图标切换)


⚠️ 避坑指南:血泪总结的 5 大雷区

坑点现象解决方案
StateList 顺序错乱按下无反馈确保“默认状态”放在 selector 最后
Vector 低版本崩溃API<21 闪退启用 vectorDrawables.useSupportLibrary = true
AnimationDrawable 不动帧动画卡第一帧onWindowFocusChanged 中 start()
Shape 内存泄漏复杂渐变卡顿避免在 RecyclerView 高频刷新项中用复杂 Gradient
Ripple 无边界水波纹溢出圆角<item android:id="@android:id/mask"> 定义裁剪区域

🌱 写在最后:Drawable 是“小工具”,更是“大智慧”

  • 性能党:用 Shape 代替 PNG 背景,安装包直降 10%+
  • 体验党:Ripple + Transition 让交互有温度
  • 架构党:自定义 Drawable 封装业务逻辑(如:带 Badge 的 Drawable)

真正的高手,往往在最基础的 API 里藏了最深的功力。
下次当你写 android:background 时,不妨多问一句:
“这里,Drawable 能做得更好吗?”


💬 互动时间
👉 你用过最巧妙的 Drawable 技巧是什么?
👉 有没有被某个 Drawable 坑到深夜的经历?

📌 延伸阅读

  • 《VectorDrawable 兼容性终极指南》
  • 《自定义 Drawable:从入门到造轮子》
  • 官方文档:Drawable Resources
总资产 0
暂无其他文章

热门文章

暂无热门文章