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:rectangle、oval、line、ring。gradient 子元素可实现线性/径向/扫描渐变:
<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_pressed、state_focused、state_enabled、state_selected、state_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>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 导入矢量图标。
① 创建 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、设备配置和初始状态,触发“按下、禁用、缩放、换密度与切换主题”
冻结入口: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:事件轨迹
不变量:图形状态与可点击语义一致,在目标密度不模糊或错位
交付证据:drawable 命中、state set、像素边界、密度截图和交互断言
实验三:章专属反例与同输入恢复
注入“selector 缺少 disabled 项,禁用按钮仍看起来可点击”,保存第一个偏离点;撤销后以完全相同的 SDK、设备状态和用户事件重放。只有drawable 命中、state set、像素边界、密度截图和交互断言一起恢复才算修复。
Fault · cancel · restore
XML drawable:反例与恢复
故障:selector 缺少 disabled 项,禁用按钮仍看起来可点击
第 1 次使用相同 SDK、设备配置、初始状态与用户事件
保持正常输入不变,仅注入“selector 缺少 disabled 项,禁用按钮仍看起来可点击”
图形状态与可点击语义一致,在目标密度不模糊或错位
drawable 命中、state set、像素边界、密度截图和交互断言