news 2026/10/6 2:37:17

Android 官方培训课程中文版精读:Material Design 中 Drawable 的使用——染色、主色提取与矢量图实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android 官方培训课程中文版精读:Material Design 中 Drawable 的使用——染色、主色提取与矢量图实战
  • 文档
  • 教程
  • 移动开发

【免费下载链接】android-training-course-in-chinese

Android官方培训课程中文版

项目地址:https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese
点击查看免费下载

本篇文章基于 Android 官方培训课程中文版(android-training-course-in-chinese)中《使用 Drawables》一课的翻译内容展开,并结合仓库内 Material Design 主题、自定义动画 与 维护兼容性 等相邻课程进行源码级佐证与延伸。读者读完本文将掌握三件具体能力:如何用一套资源为 Drawable 灵活染色以贴合主题色、如何从图片中自动提取并应用主色调、如何用单个 XML 矢量文件替代多密度位图资源并为其添加动画。

在 Material Design 应用中,图标、背景、图片与主题色之间需要保持视觉上的统一与灵活。Android 5.0(API level 21)引入了三类关键 Drawable 能力,让开发者可以用更少的资源文件实现更丰富的视觉效果:

  • Drawable 染色(Tinting):用颜色资源或主题属性给位图、Nine-Patch 图片染色;
  • 主色调提取(Palette):从图片中自动提取亮色、暗色等主色调并用于界面着色;
  • 矢量 Drawable(Vector Drawable):用单个<vector>XML 文件实现无损缩放,替代为每个屏幕密度准备一张位图的传统做法。

本课是 Material Design 系列课程(material/index.md)中的独立章节,与其主题、动画、阴影等课程互为补充。下文将以这三项能力为主线,逐层展开完整配置与调用细节。

给 Drawable 资源染色:一套资源适配整套主题

在 Android 5.0(API level 21)及以上版本,你可以借助alpha mask(透明度图层)给位图(Bitmap)和 Nine-Patch 图片染色。染色的颜色既可以写死为颜色资源(@color/...),也可以直接引用主题属性(例如?android:attr/colorPrimary),从而让图片颜色自动跟随当前主题变化。

这样做最大的收益是:你只需要创建一次颜色类资源(图标、图片),便可以在主题中自动匹配颜色,无需为每个主题色再导出一套图片。例如,当你把主题的android:colorPrimary从蓝色换成红色(自定义调色板的方式参见 material/theme.md),所有引用?android:attr/colorPrimary的图片染色会自动跟随更新。

在代码中染色:setTint()

你可以用setTint()方法将一种染色方式应用到BitmapDrawable或NinePatchDrawable对象:

// 获取一个已有的 BitmapDrawable / NinePatchDrawable BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.my_icon); // 使用主题主色进行染色,颜色会随主题自动变化 drawable.setTint(getResources().getColor(R.color.color_primary)); // 也可以直接引用主题属性对应的颜色值 TypedValue typedValue = new TypedValue(); getTheme().resolveAttribute(android.R.attr.colorPrimary, typedValue, true); drawable.setTint(typedValue.data);

注意:setTint()系列 API 属于 API level 21 的新增能力,在调用前应做好系统版本判断(版本检查代码见下文"兼容性"小节)。

在布局中染色:android:tint 与 android:tintMode

除了代码调用,你还可以在 Layout 中通过android:tint与android:tintMode属性直接声明染色颜色和混合模式(原文档此处写作initMode,标准属性名实为android:tintMode):

<ImageView android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/ic_share" android:tint="?android:attr/colorPrimary" android:tintMode="src_in" />
  • android:tint:指定染色颜色,可直接使用?android:attr/colorPrimary这类主题属性,实现"一次定义、全主题复用";
  • android:tintMode:指定颜色混合模式,常见取值如src_in(结果色 = 源与目标按 alpha 叠加,常用于图标染色)、multiply(正片叠底)等,对应底层的混合模式算法,决定颜色与图片原始像素的合成方式。

把图标统一染成主题色,是 Material Design 中保证不同状态、不同模块视觉一致性的常用手段:你只需要维护黑白底图,剩下的配色交给主题。

从图片中提取主色调:Palette 类实战

在 Material Design 界面中,常常需要让界面配色与用户看到的图片(如封面、头像、商品图)协调一致。Android Support Library v21 及更高版本提供的Palette类,可以从一张图片中提取若干种代表性颜色,供后续界面着色使用。

Palette类可以提取以下六种色调:

提取色说明
Vibrant亮色(画面中最鲜艳明亮的颜色)
Vibrant dark深亮色
Vibrant light浅亮色
Muted暗色(画面中较柔和、低饱和的暗色)
Muted dark深暗色
Muted light浅暗色

同步提取:Palette.generate()

在载入图片的后台线程中,把已解码的Bitmap对象传给静态方法Palette.generate(),即可同步完成颜色提取:

// 以下代码运行在后台线程中(Bitmap 解码与处理本身也不应放在主线程, // 参见 [graphics/displaying-bitmaps/load-bitmap.md](https://link.gitcode.com/i/87c376cc6db2f53d965541bed18551f2)) Bitmap bitmap = loadBitmapFromSource(...); Palette palette = Palette.generate(bitmap);

之所以强调在后台线程执行,是因为图片解码与主色调统计都是耗时操作,若放在 UI 线程会造成卡顿;仓库中 graphics/displaying-bitmaps/load-bitmap.md 一课对此有完整说明:Bitmap 的裁剪、解码、下载等操作不能执行在主线程。

异步提取:Palette.generateAsync()

如果无法使用后台线程,可以调用Palette.generateAsync()方法,并提供一个Palette.PaletteAsyncListener监听器,在提取完成时收到回调:

Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { // 回调在后台线程完成,回到主线程后更新 UI int vibrantColor = palette.getVibrantColor(0xFF000000); // 应用提取到的颜色,例如设置 ActionBar 或卡片背景 } });

读取提取结果

提取完成后,可以用 Palette 类提供的 getter 方法获取具体颜色,例如:

  • Palette.getVibrantColor(int defaultColor):获取亮色;
  • 同理还有getVibrantDarkColor()、getVibrantLightColor()、getMutedColor()、getMutedDarkColor()、getMutedLightColor()等对应上表六种色调的 getter。

这些 getter 都需要传入一个默认颜色参数,用于提取结果缺失时兜底,保证界面颜色总是有确定值。

添加 Gradle 依赖

要使用Palette类,需要在应用模块的 Gradle 依赖中添加 palette-v7 Support Library:

dependencies { ... compile 'com.android.support:palette-v7:21.0.+' }

说明:以上是课程成文年代(对应 Android 5.0 / Support Library r21 时代)的依赖写法;在较新版本的 Android Gradle Plugin 中,compile配置已更名为implementation,你可以按项目实际使用的构建工具版本对应替换,依赖坐标本身不变。

创建矢量 Drawable:一个 XML 文件代替一整套位图

在 Android 5.0(API level 21)及以上版本,你可以定义矢量 Drawable(Vector Drawable)用于无损拉伸图片。传统位图方案中,为了适配不同屏幕密度(mdpi/hdpi/xhdpi/xxhdpi 等),需要为同一个图标准备多份不同分辨率的 PNG;而一个矢量图片只需要一个 asset 文件,即可在不同密度与尺寸下保持清晰。

要创建矢量图片,你需要在<vector>XML 元素中定义形状。以下代码定义了一个心形:

<!-- res/drawable/heart.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" <!-- intrinsic size of the drawable --> android:height="256dp" android:width="256dp" <!-- size of the virtual canvas --> android:viewportWidth="32" android:viewportHeight="32"> <!-- draw a path --> <path android:fillColor="#8fff" android:pathData="M20.5,9.5 c-1.955,0,-3.83,1.268,-4.5,3 c-0.67,-1.732,-2.547,-3,-4.5,-3 C8.957,9.5,7,11.432,7,14 c0,3.53,3.793,6.257,9,11.5 c5.207,-5.242,9,-7.97,9,-11.5 C25,11.432,23.043,9.5,20.5,9.5z" /> </vector>

理解矢量文件的四个关键属性

  • android:width/android:height:Drawable 的固有尺寸(即 256dp),决定矢量图在未显式设置大小时的默认显示尺寸;
  • android:viewportWidth/android:viewportHeight:虚拟画布尺寸(即 32×32),pathData中的坐标均基于这个虚拟坐标系书写,显示时系统会按固有尺寸对虚拟画布做无损缩放;
  • <path>的android:fillColor:填充颜色,可使用#8fff这类带 alpha 的十六进制色值;
  • <path>的android:pathData:路径数据,描述图形的轮廓,语法与 SVG Path Data 一致。

pathData中的字母代表绘图命令,常见命令包括:M(move to,移动画笔起点)、C/c(三次贝塞尔曲线,相对/绝对坐标)、L/l(直线)、z(闭合路径)等。上例的心形正是由多条相对坐标(小写字母)贝塞尔曲线命令绘制而成。矢量图片在 Android 中由VectorDrawable对象表示。

升级:让矢量 Drawable 动起来

矢量 Drawable 的优势不仅在于静态显示,还在于可以无损地做路径变形、旋转、平移等动画——这正是 material/animations.md 中"动画矢量 Drawables"一章的内容。动画矢量 Drawable 通常由三个 XML 文件配合组成:

  1. 在res/drawable/中用<vector>定义基础矢量图;
  2. 在res/drawable/中用<animated-vector>定义动画矢量 Drawable,通过android:name找到要动画的<group>与<path>;
  3. 在res/anim/中定义一个或多个ObjectAnimator/AnimatorSet。

例如,先给矢量的 group 和 path 命名(android:name="rotationGroup"、android:name="v"),再用<animated-vector>通过 name 引用它们并挂接动画目标:

<!-- res/drawable/animvectordrawable.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vectordrawable" > <target android:name="rotationGroup" android:animation="@anim/rotation" /> <target android:name="v" android:animation="@anim/path_morph" /> </animated-vector>

其中@anim/rotation是一个将 group 旋转 360° 的ObjectAnimator,@anim/path_morph则将路径从一种形状 morph(变形)到另一种:

<!-- res/anim/path_morph.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType" /> </set>

路径 morph 有一个硬性约束:参与变形的两条路径必须拥有相同数量的命令,且每个命令的参数数量也必须一致,否则系统无法在两条路径之间做插值变形。

兼容性:API level 21 以下版本怎么处理

本课介绍的染色、矢量 Drawable 以及 Support Library 中的Palette类,大多依赖 Android 5.0(API level 21)的能力。按照 material/compatibility.md 的归纳,以下特性仅在 API level 21 及以上可用:

  • 矢量 Drawable
  • Drawable 染色
  • Activity 切换动画、触摸反馈、Reveal 动画、基于路径的动画

Palette类本身来自 v7 Support Library,可以向下兼容旧版本;但 Drawable 染色与矢量 Drawable 属平台新能力。为保证兼容性,可以在运行时检查系统版本,再决定是否启用这些 Material 特性:

// Check if we're running on Android 5.0 or higher if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Call some material design APIs here } else { // Implement this feature without material design }

同时,仓库兼容性课程还给出了一个重要的工程化建议:在res/values-v21/中提供适配新 API 的资源与样式,在res/values/中提供旧版本回退资源,并使用 style 继承避免代码重复。这样既能在 Android 5.0+ 上充分发挥矢量图与染色的优势,又不会让低版本设备上出现资源缺失。

小结与延伸阅读

本课的核心结论可以概括为三点:

  1. 染色(Tint):借助 alpha mask 与setTint()/android:tint/android:tintMode,让一套位图资源自动跟随主题色(如?android:attr/colorPrimary),实现资源的主题化复用;
  2. 主色调提取(Palette):用 palette-v7 的Palette.generate()(后台线程)或Palette.generateAsync()(带回调)从 Bitmap 中提取 Vibrant / Muted 等六种色调,让界面配色与内容图片联动;
  3. 矢量 Drawable:用单个<vector>XML(width/height定义固有尺寸,viewportWidth/Height定义虚拟画布,pathData描述路径)替代多密度位图,并可通过AnimatedVectorDrawable实现无损动画。

这三项能力共同服务于 Material Design 的"色彩统一、图形灵活、多密度自适应"目标。若想继续深入,建议按以下顺序阅读同一系列的相邻课程:

  • 开始使用 Material Design:了解主题、Layout、Elevation、CardView 等 Material 应用的整体搭建流程;
  • 使用 Material 的主题:掌握colorPrimary、colorPrimaryDark、colorAccent等调色板属性,它们是染色与提取色落地的载体;
  • 自定义动画:深入矢量 Drawable 动画、触摸反馈、Activity 切换与曲线动画的完整实现;
  • 维护兼容性:学习在 API level 21 以下版本中保留 Material 特性的完整策略与依赖配置。
  • 文档
  • 教程
  • 移动开发

【免费下载链接】android-training-course-in-chinese

Android官方培训课程中文版

项目地址:https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese
点击查看免费下载
上一篇:Moodle UI 组件库入门:基于 Hugo 与 Bootstrap 的组件文档中心实战指南
下一篇:GitHub加速完整指南:三步装好Fast-GitHub,告别等待进度条

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:37:15

ZeroTermux 离线命令手册:look 命令完整实战指南

移动开发开发工具 【免费下载链接】ZeroTermux 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/ze/ZeroTermux 点击查看 免费下载 look 是 Linux/Unix 系统中一个轻量而实用的文本检索工具&#xff0c;用于显示文件中以指定字符串开头的任意行。在 ZeroTermux&…

作者头像 李华
网站建设 2026/10/6 2:37:15

openpilot 开源驾驶辅助上手指南:335 款车免费升级智能巡航

openpilot 开源驾驶辅助上手指南&#xff1a;335 款车免费升级智能巡航 【免费下载链接】openpilot openpilot is an operating system for robotics. Currently, it upgrades the driver assistance system on 300 supported cars. 项目地址: https://gitcode.com/GitHub_Tr…

作者头像 李华
网站建设 2026/10/6 2:33:03

【学习笔记-AI工程化系列】RAG 只是 Context Engineering 的一小块-5/16

很多团队做 AI 应用&#xff0c;第一反应是&#xff1a; 模型不知道业务知识&#xff0c;那就上 RAG。 这当然没错。 如果模型没有看到公司文档、产品手册、历史工单、代码说明&#xff0c;它不可能稳定回答这些问题。但问题在于&#xff0c;很多系统上了 RAG 之后&#xff0c…

作者头像 李华
网站建设 2026/10/6 2:30:02

Nexus:Proactive Intra-GPU Disaggregation of Prefill and Decode in LLM Serving

文章主要内容和创新点 主要内容 本文聚焦于大语言模型(LLM)推理服务中预填充(prefill)和解码(decode)两个阶段的资源管理问题。预填充阶段处理完整输入提示以生成第一个输出token,属于计算密集型;解码阶段逐token生成后续输出,受内存带宽约束。现有方案存在局限:单…

作者头像 李华