XML drawable

XML drawable:保留第四版正文机制,以所有者—状态—结果合同、事件轨迹和章专属故障完成可重放验收。

学习目标

  • 能沿“XML drawable”的用户事件解释Android组件、状态所有者、线程与销毁边界。
  • 能围绕“用 XML 定义 shape、gradient、selector、layer-list 等 drawable——比 PNG 更省空间、自适应屏幕密度。”改出一个可运行结果,并用前后状态而非组件数量验收。
  • 能在旋转、进程重建、拒权、离线或无效输入中选择适用反例,定位首个状态分叉。
  • 能用双视口、大字体、焦点顺序、状态语义和对比度截图独立重放结论,并标明第四版机制与现代targetSdk政策的边界。

你的 App 塞满了 PNG 图片

按钮背景是一张 9-patch,圆角卡片是一张 PNG,选中的高亮又是一张图——你的 APK 越来越胖。XML drawable 在运行时由系统渲染,一个 2KB 的 XML 文件能替代所有屏幕密度下的 PNG(xxhdpi/xxxhdpi 各一份,加起来几十 KB)

Shape Drawable

<!-- res/drawable/rounded_background.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#FFFFFF" />
    <corners android:radius="12dp" />
    <stroke android:width="1dp" android:color="#E0E0E0" />
</shape>

支持的 shape:rectangleovallineringgradient 子元素可实现线性/径向/扫描渐变:

<gradient
    android:startColor="#FF6B6B"
    android:endColor="#FF8E53"
    android:angle="45" />

Selector(State-List)

按钮按下变暗、禁用变灰——这些状态切换用 selector 一行代码搞定:

<!-- res/drawable/button_bg.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 按下状态 -->
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#1565C0" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- 禁用状态 -->
    <item android:state_enabled="false">
        <shape>
            <solid android:color="#BDBDBD" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- 默认 -->
    <item>
        <shape>
            <solid android:color="#2196F3" />
            <corners android:radius="8dp" />
        </shape>
    </item>
</selector>

Selector 按从上到下顺序匹配——第一个匹配的 <item> 生效。支持的状态:state_pressedstate_focusedstate_enabledstate_selectedstate_checked 等。

Layer-List

把多个 drawable 叠起来:

<layer-list xmlns:android="...">
    <item>
        <shape><solid android:color="#FFF"/></shape>
    </item>
    <item android:top="2dp" android:bottom="2dp">
        <shape><solid android:color="#E0E0E0"/></shape>
    </item>
</layer-list>
四种常用 XML drawable 类型每种由不同的根标签声明,覆盖背景、叠层、状态切换、点击反馈Shape<shape>根标签
纯矢量背景:圆角 / 渐变 / 描边 / 纯色
Layer-List<layer-list>根标签
多层叠加,如阴影 / 边框组合
Selector / State-Listdefaultpressed<selector>根标签
按 state 自动切换:pressed / focused / checked / default
Ripple<ripple>根标签
Material 点击波纹反馈
XML drawable:矢量可缩放、按状态自动切换、省图片资源android:background="@drawable/xxx" 即可引用
四种常用 XML drawable:shape(纯矢量背景)、layer-list(多层叠加)、selector(按 state 切换)、ripple(点击波纹)。都用 XML 根标签声明,矢量可缩放、省图片资源,在 android:background 中引用。

Vector Drawable

用 SVG 路径描述图标——任意缩放不变形、一个文件通吃所有屏幕:

<vector android:width="24dp" android:height="24dp"
    android:viewportWidth="24" android:viewportHeight="24">
    <path
        android:fillColor="#000"
        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10..." />
</vector>

Android Studio 内置 Vector Asset 工具——直接从 Material Icons 导入矢量图标。

分步1 / 4

① 创建 shape drawable

res/drawable/ 下新建 XML 文件,根元素 <shape> 设置 android:shape="rectangle"(或 oval/line/ring)。系统在运行时将 XML 解析为位图,自动适配当前屏幕密度。

容易踩的坑

小结

  • XML drawable 替代 PNG → 省空间、自适应密度、运行时渲染
  • shape 画基本图形;gradient 画渐变;corners 设圆角;stroke 加描边
  • selector 根据 View 状态(按下/禁用/选中)自动切换 drawable
  • layer-list 叠加多层 drawable;vector 用路径描述图标 → 无限缩放
  • selector 顺序:默认 item 放最后,状态 item 放前面

练习

问题 1:“第22章 XML Drawables”覆盖哪些正式节点和项目主线?

问题 2:怎样建立本页最小可执行实验?

问题 3:为什么只在正常点击路径运行不能证明完成?

问题 4:怎样设计能推翻当前实现的反例?

问题 5:从第4版语境迁移到现代目标SDK时如何控制变量?

问题 6:本页达到独立交接标准需要什么?

名词解释

本章出现的专业名词,用大白话再讲一遍。

Shape Drawable

用 XML 定义的几何图形(矩形/椭圆/线/环)。支持纯色(solid)、圆角(corners)、描边(stroke)、渐变(gradient)等属性。替代 PNG 背景图。

Selector(State-List)

根据 View 状态(按下/禁用/选中/聚焦)自动切换 drawable 的 XML 定义。创建按钮、列表项等交互反馈的标准方式。

Vector Drawable

用 XML 路径(pathData)描述的矢量图。与分辨率无关——任意缩放不失真,一个文件适用所有屏幕密度。

“XML drawable”不使用未获授权的纸书正文;InformIT出版信息授权电子版完整目录只用于确认第四版32章、269个正式目录节点和时代语境,第四版官方勘误用于识别工具链变更。下列中文解释、图示、交互、代码与练习均为独立教学重写,平台行为再以Android Developers的一手文档复核。

为什么“XML drawable”必须回到可观察状态

“XML drawable”的学习结果不是记住类名,而是能预测“用 XML 定义 shape、gradient、selector、layer-list 等 drawable——比 PNG 更省空间、自适应屏幕密度。”在一次输入、一次重建和一次失败中的不同状态,并指出哪条Android合同产生差异。

第四版机制逐项深读

22. XML Drawables

在“XML drawable”中,“22. XML Drawables”通过资源限定符和主题属性把内容与设备配置解耦;最终值由资源匹配和主题继承共同决定。

Making Uniform Buttons

在“XML drawable”中,验证“Making Uniform Buttons”只改变一个生命周期或外部条件,保存操作、原始日志、状态快照和用户可见断言。

Shape Drawables

在“XML drawable”中,验证“Shape Drawables”在日夜主题、不同密度和字体缩放下比较像素边界、对比度与状态反馈。

State List Drawables

在“XML drawable”中,验证“State List Drawables”在日夜主题、不同密度和字体缩放下比较像素边界、对比度与状态反馈。

Layer List Drawables

在“XML drawable”中,验证“Layer List Drawables”在日夜主题、不同密度和字体缩放下比较像素边界、对比度与状态反馈。

For the More Curious: Why Bother with XML Drawables?

在“XML drawable”中,“For the More Curious: Why Bother with XML Drawables?”通过资源限定符和主题属性把内容与设备配置解耦;最终值由资源匹配和主题继承共同决定。

For the More Curious: Mipmap Images

在“XML drawable”中,“For the More Curious: Mipmap Images”用于推翻“用 XML 定义 shape、gradient、selector、layer-list 等 drawable——比 PNG 更省空间、自适应屏幕密度。”的顺利路径:先写预期,再引入一个边界输入、重建或平台差异,并用状态、日志与用户结果解释首个分叉。

For the More Curious: 9-Patch Images

在“XML drawable”中,“For the More Curious: 9-Patch Images”用于推翻“用 XML 定义 shape、gradient、selector、layer-list 等 drawable——比 PNG 更省空间、自适应屏幕密度。”的顺利路径:先写预期,再引入一个边界输入、重建或平台差异,并用状态、日志与用户结果解释首个分叉。

Challenge: Button Themes

在“XML drawable”中,“Challenge: Button Themes”的复用不能吞掉状态语义;pressed、focused、disabled与checked都要有可辨反馈。

“XML drawable”验收回顾

“XML drawable”只有在双视口、大字体、焦点顺序、状态语义和对比度截图能够从相同基线再次得到相同断言时才通过;第四版机制与现代平台政策分别记录,不用新API名称掩盖旧行为。

← 上一页:样式与主题 · 下一页:深入学习intent和任务 →

章专属可重放状态实验

先预测“按下、禁用、缩放、换密度与切换主题”发生后,Drawable 资源、View state 与资源匹配器应怎样改变边角、描边、图层、pressed/disabled 状态和密度;再操作三个实验。第四版示例与当前 Android 政策分别记录,实验不把新 API 名称倒填为原书内容。

实验一:所有者—状态—结果合同

选择任一正式目录节点和正常/边界场景,检查它是否真的进入本章状态合同。目录标题只有同时出现在解释、可视状态和交付证据中才算覆盖。

Owner · state · observable result

XML drawable:状态合同

用 shape、selector、layer-list 与 9-patch 表达可缩放状态图形

验证场景

第四版正式目录节点

xml-drawables · 正常任务

22. XML Drawables固定 SDK、设备配置和初始状态,触发“按下、禁用、缩放、换密度与切换主题”

状态所有者Drawable 资源、View state 与资源匹配器
受控状态边角、描边、图层、pressed/disabled 状态和密度
触发事件按下、禁用、缩放、换密度与切换主题

冻结入口:22. XML Drawables

记录Drawable 资源、View state 与资源匹配器的初始边角、描边、图层、pressed/disabled 状态和密度

观察:drawable 命中、state set、像素边界、密度截图和交互断言中的“22. XML Drawables”轨迹

预期:由Drawable 资源、View state 与资源匹配器提交边角、描边、图层、pressed/disabled 状态和密度,并持续满足“图形状态与可点击语义一致,在目标密度不模糊或错位”

实验二:事件与生命周期轨迹

沿五次转换逐步执行“按下、禁用、缩放、换密度与切换主题”。每一步只允许Drawable 资源、View state 与资源匹配器按职责提交状态,并持续核对“图形状态与可点击语义一致,在目标密度不模糊或错位”。

Deterministic event replay

XML drawable:事件轨迹

选择一次状态转换1 / 5

不变量:图形状态与可点击语义一致,在目标密度不模糊或错位

交付证据:drawable 命中、state set、像素边界、密度截图和交互断言

实验三:章专属反例与同输入恢复

注入“selector 缺少 disabled 项,禁用按钮仍看起来可点击”,保存第一个偏离点;撤销后以完全相同的 SDK、设备状态和用户事件重放。只有drawable 命中、state set、像素边界、密度截图和交互断言一起恢复才算修复。

Fault · cancel · restore

XML drawable:反例与恢复

故障:selector 缺少 disabled 项,禁用按钮仍看起来可点击

1. 冻结输入一致

第 1 次使用相同 SDK、设备配置、初始状态与用户事件

2. 注入边界一致

保持正常输入不变,仅注入“selector 缺少 disabled 项,禁用按钮仍看起来可点击”

3. 检查所有者一致

图形状态与可点击语义一致,在目标密度不模糊或错位

4. 核对结果一致

drawable 命中、state set、像素边界、密度截图和交互断言

讨论

评论区加载中…