Android中的13种Drawable小结

在 Android 开发中,Drawable 是一种可绘制对象,用于表示图形或图像资源,广泛应用于 UI 设计,如设置 View 的背景、按钮样式、图标等。Drawable 提供了多种类型,每种类型有其独特的功能和使用场景。本文将详细总结 Android 中的 13 种 Drawable,包括其定义、用途、代码示例、XML 配置,以及常见问题和注意事项,结合中文讲解,适合初学者和进阶开发者。


一、Drawable 概述

  • 定义:Drawable 是一个抽象类,位于 android.graphics.drawable 包中,表示可以在画布(Canvas)上绘制的对象。
  • 作用
  • 设置 View 的背景(如按钮、布局)。
  • 定义控件的外观(如形状、渐变、动画)。
  • 提供可扩展的图形资源,替代直接使用图片(如 PNG)。
  • 使用方式
  • XML 定义:在 res/drawable 目录下创建 XML 文件。
  • 代码创建:通过 Java/Kotlin 动态创建 Drawable。
  • 资源引用:在布局或代码中引用 Drawable。
  • 优势
  • 轻量级,减少 APK 大小。
  • 支持动态调整(如颜色、大小)。
  • 可实现复杂效果(如状态切换、动画)。

二、Android 中的 13 种 Drawable

以下是 Android 中常见的 13 种 Drawable 类型,涵盖基础、组合和高级类型,逐一讲解其特点、用法和示例。

1. BitmapDrawable

  • 定义:表示位图图片(如 PNG、JPG)。
  • 用途:加载图片资源作为 View 背景或前景。
  • XML 示例res/drawable/bitmap_example.xml):
  <bitmap
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:src="@drawable/image"
      android:tileMode="repeat" />
  • 代码示例(Kotlin):
  val bitmapDrawable = BitmapDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.image))
  view.background = bitmapDrawable
  • 属性
  • android:src:指定图片资源。
  • android:tileMode:平铺模式(repeatmirrorclamp)。
  • android:gravity:图片对齐方式。
  • 注意:图片过大可能导致内存问题,建议优化图片大小。

2. ColorDrawable

  • 定义:表示纯色填充。
  • 用途:设置单一颜色背景,常用于简单背景或占位符。
  • XML 示例res/drawable/color_example.xml):
  <color
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:color="#FF0000" />
  • 代码示例(Kotlin):
  val colorDrawable = ColorDrawable(Color.RED)
  view.background = colorDrawable
  • 属性
  • android:color:颜色值(如 #FF0000)。
  • 注意:简单高效,适合快速设置背景颜色。

3. ShapeDrawable

  • 定义:通过 XML 定义几何形状(如矩形、圆形)。
  • 用途:创建自定义形状背景,如圆角矩形、边框。
  • XML 示例res/drawable/shape_example.xml):
  <shape
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle">
      <solid android:color="#FF0000" />
      <corners android:radius="10dp" />
      <stroke
          android:width="2dp"
          android:color="#000000" />
  </shape>
  • 代码示例(Kotlin):
  val shapeDrawable = GradientDrawable().apply {
      shape = GradientDrawable.RECTANGLE
      setColor(Color.RED)
      cornerRadius = 10f
      setStroke(2, Color.BLACK)
  }
  view.background = shapeDrawable
  • 属性
  • android:shape:形状(rectangleovallinering)。
  • <solid>:填充颜色。
  • <corners>:圆角半径。
  • <stroke>:边框宽度和颜色。
  • 注意:灵活性高,推荐用于自定义按钮或背景。

4. GradientDrawable

  • 定义:表示渐变填充,支持线性、径向和扫描渐变。
  • 用途:创建渐变背景或按钮效果。
  • XML 示例res/drawable/gradient_example.xml):
  <shape
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle">
      <gradient
          android:startColor="#FF0000"
          android:endColor="#0000FF"
          android:angle="45" />
      <corners android:radius="10dp" />
  </shape>
  • 代码示例(Kotlin):
  val gradientDrawable = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(Color.RED, Color.BLUE))
  gradientDrawable.cornerRadius = 10f
  view.background = gradientDrawable
  • 属性
  • android:startColorandroid:endColor:渐变起始和结束颜色。
  • android:angle:线性渐变角度(0、45、90 等)。
  • android:type:渐变类型(linearradialsweep)。
  • 注意:渐变性能较好,适合美化 UI。

5. LayerDrawable

  • 定义:将多个 Drawable 叠加显示。
  • 用途:组合多个图形效果,如背景叠加前景。
  • XML 示例res/drawable/layer_example.xml):
  <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
      <item>
          <shape android:shape="rectangle">
              <solid android:color="#FF0000" />
          </shape>
      </item>
      <item android:top="10dp" android:left="10dp">
          <shape android:shape="rectangle">
              <solid android:color="#0000FF" />
          </shape>
      </item>
  </layer-list>
  • 代码示例(Kotlin):
  val layerDrawable = LayerDrawable(arrayOf(
      ColorDrawable(Color.RED),
      ColorDrawable(Color.BLUE).apply { setBounds(10, 10, 0, 0) }
  ))
  view.background = layerDrawable
  • 属性
  • <item>:定义每一层 Drawable。
  • android:topandroid:left:偏移量。
  • 注意:可实现复杂叠加效果,注意层级顺序。

6. StateListDrawable

  • 定义:根据 View 状态(如按下、选中)切换不同 Drawable。
  • 用途:实现按钮的按下、选中等交互效果。
  • XML 示例res/drawable/statelist_example.xml):
  <selector xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:state_pressed="true">
          <shape android:shape="rectangle">
              <solid android:color="#FF0000" />
          </shape>
      </item>
      <item android:state_selected="true">
          <shape android:shape="rectangle">
              <solid android:color="#00FF00" />
          </shape>
      </item>
      <item>
          <shape android:shape="rectangle">
              <solid android:color="#0000FF" />
          </shape>
      </item>
  </selector>
  • 代码示例(Kotlin):
  val stateListDrawable = StateListDrawable().apply {
      addState(intArrayOf(android.R.attr.state_pressed), ColorDrawable(Color.RED))
      addState(intArrayOf(android.R.attr.state_selected), ColorDrawable(Color.GREEN))
      addState(intArrayOf(), ColorDrawable(Color.BLUE))
  }
  view.background = stateListDrawable
  • 属性
  • android:state_pressed:按下状态。
  • android:state_selected:选中状态。
  • android:state_focused:焦点状态。
  • 注意:常用于按钮或可点击 View,优先级按顺序匹配。

7. LevelListDrawable

  • 定义:根据级别(level)切换不同 Drawable。
  • 用途:实现多级显示,如进度条或电池电量图标。
  • XML 示例res/drawable/levellist_example.xml):
  <level-list xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:maxLevel="0" android:drawable="@drawable/low" />
      <item android:maxLevel="50" android:drawable="@drawable/mid" />
      <item android:maxLevel="100" android:drawable="@drawable/high" />
  </level-list>
  • 代码示例(Kotlin):
  val levelListDrawable = LevelListDrawable().apply {
      addLevel(0, 0, resources.getDrawable(R.drawable.low))
      addLevel(1, 50, resources.getDrawable(R.drawable.mid))
      addLevel(51, 100, resources.getDrawable(R.drawable.high))
  }
  view.background = levelListDrawable
  levelListDrawable.level = 60 // 显示 mid
  • 属性
  • android:maxLevel:最大级别。
  • android:drawable:对应的 Drawable。
  • 注意:通过 setLevel(int) 动态切换。

8. TransitionDrawable

  • 定义:在两个 Drawable 之间实现渐变过渡动画。
  • 用途:创建背景淡入淡出效果。
  • XML 示例res/drawable/transition_example.xml):
  <transition xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:drawable="@drawable/image1" />
      <item android:drawable="@drawable/image2" />
  </transition>
  • 代码示例(Kotlin):
  val transitionDrawable = TransitionDrawable(arrayOf(
      resources.getDrawable(R.drawable.image1),
      resources.getDrawable(R.drawable.image2)
  ))
  view.background = transitionDrawable
  transitionDrawable.startTransition(1000) // 1秒过渡
  • 方法
  • startTransition(duration):开始过渡。
  • reverseTransition(duration):反向过渡。
  • 注意:适合简单的渐变动画。

9. InsetDrawable

  • 定义:在 Drawable 周围添加内边距。
  • 用途:调整背景与 View 的间距。
  • XML 示例res/drawable/inset_example.xml):
  <inset
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:drawable="@drawable/image"
      android:inset="10dp" />
  • 代码示例(Kotlin):
  val insetDrawable = InsetDrawable(resources.getDrawable(R.drawable.image), 10)
  view.background = insetDrawable
  • 属性
  • android:inset:统一内边距。
  • android:insetTopandroid:insetLeft:单独设置。
  • 注意:常与 LayerDrawable 结合使用。

10. ClipDrawable

  • 定义:根据级别(level)裁剪 Drawable,显示部分内容。
  • 用途:实现进度条或裁剪效果。
  • XML 示例res/drawable/clip_example.xml):
  <clip
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:drawable="@drawable/image"
      android:clipOrientation="horizontal"
      android:gravity="left" />
  • 代码示例(Kotlin):
  val clipDrawable = ClipDrawable(resources.getDrawable(R.drawable.image), Gravity.LEFT, ClipDrawable.HORIZONTAL)
  view.background = clipDrawable
  clipDrawable.level = 5000 // 显示 50%
  • 属性
  • android:clipOrientation:裁剪方向(horizontalvertical)。
  • android:gravity:裁剪起点。
  • 注意:级别范围 0-10000(0% 到 100%)。

11. ScaleDrawable

  • 定义:根据级别缩放 Drawable。
  • 用途:实现缩放动画或动态调整大小。
  • XML 示例res/drawable/scale_example.xml):
  <scale
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:drawable="@drawable/image"
      android:scaleWidth="50%"
      android:scaleHeight="50%"
      android:scaleGravity="center" />
  • 代码示例(Kotlin):
  val scaleDrawable = ScaleDrawable(resources.getDrawable(R.drawable.image), Gravity.CENTER, 0.5f, 0.5f)
  view.background = scaleDrawable
  scaleDrawable.level = 5000 // 缩放至 50%
  • 属性
  • android:scaleWidthandroid:scaleHeight:缩放比例。
  • android:scaleGravity:缩放中心。
  • 注意:级别范围 0-10000。

12. NinePatchDrawable

  • 定义:基于 .9.png 图片,支持拉伸区域和填充区域。
  • 用途:创建可拉伸的背景(如聊天气泡)。
  • XML 示例res/drawable/ninepatch_example.xml):
  <nine-patch
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:src="@drawable/ninepatch_image" />
  • 代码示例(Kotlin):
  val ninePatchDrawable = NinePatchDrawable(resources, BitmapFactory.decodeResource(resources, R.drawable.ninepatch_image))
  view.background = ninePatchDrawable
  • 注意
  • 需要 .9.png 文件,使用 Android Studio 的 9-Patch 工具编辑。
  • 拉伸区域(黑线)定义在图片边框。

13. AnimationDrawable

  • 定义:实现帧动画,通过切换多张图片。
  • 用途:创建加载动画或简单序列动画。
  • XML 示例res/drawable/animation_example.xml):
  <animation-list
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:oneshot="false">
      <item android:drawable="@drawable/frame1" android:duration="200" />
      <item android:drawable="@drawable/frame2" android:duration="200" />
      <item android:drawable="@drawable/frame3" android:duration="200" />
  </animation-list>
  • 代码示例(Kotlin):
  val animationDrawable = view.background as AnimationDrawable
  animationDrawable.start() // 开始动画
  • 属性
  • android:oneshot:是否单次播放。
  • android:duration:每帧持续时间。
  • 注意:适合简单动画,复杂动画推荐使用 Lottie。

三、完整代码示例

以下是一个结合多种 Drawable 的 Android 示例,展示按钮背景切换和动画效果。

import android.graphics.drawable.AnimationDrawable
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)

        // 设置 StateListDrawable(按下和默认状态)
        val stateListDrawable = StateListDrawable().apply {
            addState(intArrayOf(android.R.attr.state_pressed), ColorDrawable(Color.RED))
            addState(intArrayOf(), GradientDrawable().apply {
                shape = GradientDrawable.RECTANGLE
                setColor(Color.BLUE)
                cornerRadius = 10f
            })
        }
        button.background = stateListDrawable

        // 设置 AnimationDrawable(点击触发动画)
        button.setOnClickListener {
            val animationDrawable = AnimationDrawable().apply {
                addFrame(ColorDrawable(Color.GREEN), 500)
                addFrame(ColorDrawable(Color.YELLOW), 500)
                isOneShot = false
            }
            button.background = animationDrawable
            animationDrawable.start()
        }
    }
}
  • 布局文件res/layout/activity_main.xml):
  <Button
      android:id="@+id/button"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="点击切换背景" />
  • 说明
  • 默认显示蓝色圆角背景,按下显示红色。
  • 点击按钮触发绿色-黄色循环动画。

四、常见问题及注意事项

  1. 性能问题
  • BitmapDrawable:大图片可能导致内存溢出(OOM),建议压缩图片:
    kotlin val options = BitmapFactory.Options().apply { inSampleSize = 2 } // 2倍压缩 val bitmap = BitmapFactory.decodeResource(resources, R.drawable.image, options)
  • AnimationDrawable:帧数过多可能卡顿,推荐 Lottie 替代复杂动画。
  1. 兼容性
  • API 差异:部分属性(如 GradientDrawable 的 android:angle)在低版本可能无效,需测试。
  • VectorDrawable(未列为第 13 种,因其为独立类型):
    • Android 5.0+ 原生支持,需启用 vectorDrawables.useSupportLibrary = true
      gradle android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
  1. 资源管理
  • 回收 BitmapDrawable:
    kotlin (view.background as? BitmapDrawable)?.bitmap?.recycle()
  • 停止 AnimationDrawable:
    kotlin (view.background as? AnimationDrawable)?.stop()
  1. 动态修改
  • 动态更新 Drawable 属性(如颜色):
    kotlin (view.background as? GradientDrawable)?.setColor(Color.GREEN)
  • 确保 Drawable 支持 mutate() 避免影响其他 View:
    kotlin view.background = view.background.mutate()
  1. Android 4.4+ 注意
  • Chromium 引擎:WebView 支持 SVG(可通过 VectorDrawable 实现)。
  • 性能优化:启用硬件加速:
    xml <application android:hardwareAccelerated="true">

五、学习建议与实践

  1. 学习路径
  • 掌握基础 Drawable(BitmapDrawable、ColorDrawable、ShapeDrawable)。
  • 学习组合 Drawable(LayerDrawable、StateListDrawable)。
  • 实现动画效果(AnimationDrawable、TransitionDrawable)。
  • 探索 VectorDrawable 和 Lottie(高级)。
  1. 实践项目
  • 简单项目:创建圆角按钮,切换按下状态。
  • 进阶项目:实现进度条(ClipDrawable)或电池电量(LevelListDrawable)。
  • 高级项目:结合 WebView 加载 SVG 或动态生成 Drawable。
  1. 调试工具
  • Android Studio Layout Inspector:检查 View 的 Drawable。
  • Logcat:记录 Drawable 加载错误。
  • Drawable Preview:在 res/drawable 预览 XML 效果。
  1. 推荐资源
  • Android 官方文档:https://developer.android.com/reference/android/graphics/drawable/Drawable
  • Drawable 指南:https://developer.android.com/guide/topics/resources/drawable-resource
  • 9-Patch 工具:https://developer.android.com/studio/write/draw9patch

六、总结

  • 13 种 Drawable
  1. BitmapDrawable:加载位图。
  2. ColorDrawable:纯色填充。
  3. ShapeDrawable:自定义形状。
  4. GradientDrawable:渐变填充。
  5. LayerDrawable:多层叠加。
  6. StateListDrawable:状态切换。
  7. LevelListDrawable:级别切换。
  8. TransitionDrawable:渐变过渡。
  9. InsetDrawable:内边距。
  10. ClipDrawable:裁剪显示。
  11. ScaleDrawable:缩放显示。
  12. NinePatchDrawable:可拉伸图片。
  13. AnimationDrawable:帧动画。
  • 使用方式
  • XML 定义:简洁,适合静态效果。
  • 代码创建:灵活,适合动态调整。
  • 注意事项
  • 性能优化:避免大图片,回收资源。
  • 兼容性:测试低版本 API。
  • 动态修改:使用 mutate() 避免冲突。
  • 推荐
  • 优先使用 ShapeDrawable 和 GradientDrawable 替代图片。
  • 复杂动画考虑 Lottie。

如果需要更详细的代码示例(如复杂 StateListDrawable、Lottie 集成)或特定 Drawable 的深入讲解,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注