安卓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 官方资源 或 菜鸟教程示例。

相关推荐
c***21292 小时前
Springboot3学习(5、Druid使用及配置)
android·学习
修炼者3 小时前
【Android 进阶】别再强转 Context 了!手把手教你优雅解耦 View 与 Activity
android·android studio
x***01063 小时前
SpringSecurity+jwt实现权限认证功能
android·前端·后端
程序员江同学3 小时前
线下活动|2025 Kotlin 中文开发者大会北京分会场
android·kotlin
李坤林4 小时前
Android Vulkan 开启VK_GOOGLE_DISPLAY_TIMING 后,一个vsync 会释放两个imageBuffer现象分析
android·vulkan
Jerry4 小时前
Compose 状态思维
android
k***45995 小时前
MySQL----case的用法
android·数据库·mysql
r***86986 小时前
Plugin ‘mysql_native_password‘ is not loaded`
android·数据库·mysql
v***59836 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
不用89k7 小时前
Android无法区分USB摄像头是哪一个
android