安卓Drawable分类

基于你提供的详尽分类框架,我结合最新实践补充底层原理、实用技巧及进阶用法,帮助开发者更系统化地掌握 Drawable 体系:


⚙️ ​一、底层机制与核心原理

  1. Drawable 基类关键方法

    • draw(Canvas canvas):抽象绘制方法,所有子类必须实现(如 BitmapDrawable 绘制位图、ColorDrawable 填充纯色)
    • setBounds(Rect bounds):定义绘制区域,触发 onBoundsChange() 回调
    • setLevel(int level):控制动态效果(如 ClipDrawable 裁剪比例)
    • setState(int[] stateSet):响应视图状态变化(如 StateListDrawable 的按下/聚焦状态)
  2. 资源复用与性能优化

    • 共享资源BitmapDrawable 默认共享位图资源,调用 mutate() 可创建独立副本避免相互影响
    • 自动压缩 :AAPT 工具会优化 res/drawable 中的 PNG 图片(如 256 色转 8 位),若需原图应放 res/raw/

🎨 ​二、进阶分类与使用场景扩展

类别 核心子类 最佳实践
基础图形 ColorDrawable 纯色背景,优先用 @color 资源而非硬编码
ShapeDrawable 矩形/圆角/描边,替代简单图片减少资源体积
GradientDrawable 支持线性/径向/扫描渐变,替代渐变图片
动态响应 StateListDrawable 状态顺序敏感!​从上到下匹配,首个匹配项生效(默认状态应放最后)
RippleDrawable 水波纹效果需嵌套 <item> 定义背景,避免遮盖内容
组合变换 LayerDrawable 图层顺序=绘制顺序,​最后一项显示在最顶层
InsetDrawable 为其他 Drawable 添加内边距,避免文本贴边
ClipDrawable 进度条首选!level 范围 0(全剪)~10000(全显)
矢量与动画 VectorDrawable 图标首选,适配多分辨率屏幕,需兼容库支持 API <21
AnimatedVectorDrawable 路径变形动画,结合 <target> 指定动画作用对象

⚡️ ​三、高频问题解决方案

  1. ​**.9 图片使用规范**​

    • 必须放 res/drawable/mipmap/ 目录无效
    • AS 要求保留黑边(反编译 APK 获取带黑线的原图)
  2. 动态创建技巧

    ini 复制代码
    // 代码创建渐变按钮背景
    val gradient = GradientDrawable().apply {
      shape = GradientDrawable.RECTANGLE
      cornerRadius = 16.dpToPx() // 转换 dp 为像素
      colors = intArrayOf(Color.BLUE, Color.CYAN)
    }
    button.background = gradient
  3. 性能陷阱规避

    • 避免嵌套超过 3 层的 StateListDrawable
    • 复杂图形用 VectorDrawable 替代多张位图

🛠️ ​四、XML 实战示例:带按压效果的渐变按钮

xml 复制代码
<!-- res/drawable/btn_gradient_selector.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 按压状态:深色渐变 -->
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="8dp" />
            <gradient
                android:startColor="#FF416C"
                android:endColor="#FF4B2B"
                android:angle="45"/>
        </shape>
    </item>
    <!-- 默认状态:亮色渐变 -->
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="8dp" />
            <gradient
                android:startColor="#36D1DC"
                android:endColor="#5B86E5"
                android:angle="45"/>
        </shape>
    </item>
</selector>

通过 android:angle 控制渐变方向,state_pressed 区分状态


💎 ​总结建议

  • 优先矢量 :图标/简单图形用 VectorDrawable,减少分辨率适配成本
  • 慎用位图 :复杂图片选 WebP 格式,.9.png 用于特殊拉伸需求
  • 状态精简StateListDrawable 的状态匹配链尽量简短
  • 组合创新LayerDrawable + ClipDrawable 可实现动态进度条+背景叠加

更多实践案例可参考 Android Developers 官方资源 或 菜鸟教程示例。

相关推荐
huibin1478523691 小时前
dumpsys alarm 简介
android
柯南二号4 小时前
【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会
android·设计模式·抽象工厂模式
TsengOnce10 小时前
MySQL 性能调优与 SQL 优化的核心利器
android·sql·mysql
熊大与iOS11 小时前
iOS 长截图的完美实现方案 - 附Demo源码
android·算法·ios
独行soc12 小时前
2025年渗透测试面试题总结-42(题目+回答)
android·数据库·安全·adb·面试·渗透测试·sqlite
千里马学框架13 小时前
安卓15 audio新专题发布:安卓系统手机车机音频audio子系统深入实战开发专题
android·智能手机·音视频
没有了遇见14 小时前
Android 虚拟环境之虚拟环境检测<完结版>
android
liang_jy14 小时前
Android 单元测试(二)—— 高级 Mock 技术
android·面试·单元测试