Vector Drawable是基于XML的Android向量图形格式,可以创建可自定义缩放的图像而不损失质量。与PNG和JPEG不同,向量将几何轮廓和填充作为文本指令存储,这样可以实现最小的文件大小和适应任何屏幕密度。根据Android Developers(2026)文档,Vector Drawable相比于不同分辨率的位图资源集,平均可将APK大小减少40– 60%。
主要内容
Vector Drawable是一种Android资源,以XML格式表示向量图像,基于SVG(Scalable Vector Graphics)规范。Google在Android 5.0(API 21)中引入了这种格式,作为图标、插图和其他界面图形元素的位图图像替代方案。
与PNG不同,PNG将图像存储为固定大小的像素数组,而Vector Drawable通过数学方式描述形状 — 通过点坐标、Bezier曲线、填充和轮廓。这意味着一个向量图像可以替代达六个PNG文件用于不同的屏幕密度(mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi、nodpi),这样可以根本性地简化图形资源的维护。
该格式不仅支持静态图像,还支持通过AnimatedVectorDrawable实现的动画,以及通过主题属性实现的暗色主题适配和自定义颜色。从AAndroid 7.0(API 24)开始,Vector Drawable还支持渐变填充和复杂的剪切操作(clipPath),进一步扩展了设计的可能性。
每个Vector Drawable包含根元素vector,带有宽度、高度和viewPort参数 — 一个虚拟坐标系,形状在其中绘制。内部包含组(group)和路径(path),其中path通过一系列指令定义几何形状:M(moveTo)、L(lineTo)、C(cubicTo)、Z(close)等。每个path都可以有自己的填充(fillColor)和轮廓(strokeColor),这些可以引用主题资源。
额外元素包括用于剪切的clip-path、用于渐变过渡的gradient以及通过android:theme属性实现的暗色主题适配属性。Vector Drawable中的所有颜色都可以定义为对主题属性的引用(例如?attr/colorPrimary),这样在切换主题时可以改变图标的外观,而无需复制资源。
Vector Drawable的XML文件放置在res/drawable/目录中,并以<vector>作为根元素。内部可以有嵌套的<group>用于组织层级结构,以及<path>用于描述轮廓。每个path都包含pathData属性 — 以SVG路径格式编写的绘图指令字符串。
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/ic_launcher_background"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"
android:strokeWidth="1"
android:strokeColor="#333333"/>
</vector>
在示例中,描述了一个在24×24的viewPort中半径为10单位的圆。fillColor参数引用颜色资源,strokeWidth和strokeColor则定义轮廓。width和height的尺寸以dp为单位 — 这确保在不同像素密度的屏幕上正确缩放,而无需额外的变换。
group元素可以将多个path分组并应用共同的变换:旋转(rotation)、平移(translateX、translateY)和缩放(scaleX、scaleY)。分组可以嵌套,从而在不损害性能的情况下创建由数百个元素组成的复杂层级结构。
<vector ...>
<group android:name="arrow_group"
android:pivotX="12"
android:pivotY="12"
android:rotation="90">
<path .../>
</group>
</vector>
带有pivotX/pivotY属性的分组用于动画:可以独立地旋转或缩放图像的一部分,而不影响其他元素,这对于创建动态状态图标(例如加载→成功)尤其有用。
在向量和位图图形之间的选择取决于使用场景。Vector Drawable非常适合图标、插图和细节较少的界面元素,而拍摄的照片和包含数千种颜色的复杂图像则保持位图格式。
| 参数 | Vector Drawable | PNG |
|---|---|---|
| 缩放 | 不损失质量 | 放大时损失 |
| 文件大小 | 0.5–5 KB | 每分辨率10–100 KB |
| 文件数量 | 1 XML | 6 PNG (mdpi–xxxhdpi) |
| 动画 | 支持 | 仅帧更换 |
| 主题适配 | 通过?attr | 单独的组 |
| 复杂场景 | 有限 | 任意 |
根据Android Performance Patterns(Google I/O 2016),对于拥有大量图形资源的应用程序,将PNG图标替换为Vector Drawable可将APK大小减少40– 60%。但是,在渲染包含数百个路径的复杂向量时,CPU负荷会增加,因此对于动画和频繁重绘,建议使用缓存的位图。
Vector Drawable最适合界面图标(工具栏、导航、状态)、标志、简单插图和动态元素。要支持多个屏幕时,这种格式尤其有利:不用为六种密度生成PNG,只需一个XML文件就够了。这样可以简化设计维护并消除尺寸不匹配的错误。对于照片和具有真实渐变的图像,仍然使用带有WebP压缩的位图格式。
Android通过两种机制支持Vector Drawable动画:AnimatedVectorDrawable(从API 21可用)和AnimatedStateListDrawable。前者可以将路径属性进行动画化处理 — 旋转、移动、颜色和形状的变化。后者在不同状态(按压、选中)之间切换时提供平滑过渡。
AnimatedVectorDrawable使用三个XML文件:Vector Drawable本身、带有动画描述的ObjectAnimator以及将目标(组或路径的名称)与动画器连接起来的连接AnimatedVectorDrawable。动画可以改变fillColor、strokeColor、rotation、translateX/Y、scaleX/Y,甚至是pathData — 也就是说,可以将一个形状平滑地变换为另一个形状(形态转变)。
考虑一个动画,其中“加号”图标变成“叉号”图标。主要限制:路径数据指令的数量在初始状态和最终状态中必须相同,否则动画将无法工作。
<!-- res/drawable/anim_plus_to_close.xml -->
<animated-vector xmlns:android="...">
<target
android:name="plus_path"
android:animation="@anim/plus_to_close"/>
</animated-vector>
ObjectAnimator plus_to_close动画将pathData属性从初始的“加号”形状变为“叉号”形状,历时300毫秒。系统自动在两组SVG路径指令之间插值坐标。这种动画广泛应用于Material Design中,实现按钮和图标状态的平滑过渡。
让我们看一个支持暗色主题的返回箭头图标的完整XML向量示例。颜色通过引用主题属性来定义,这样在切换亮暗主题时可以自动改变图标颜色,而无需复制资源。
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<group android:name="arrow">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</group>
</vector>
带有?attr/colorControlNormal值的android:tint参数会自动应用控件的系统颜色 — 在亮色主题中为深灰色,在暗色主题中为白色。名为arrow的组允许通过AnimatedVectorDrawable对这个图标进行动画化。
要在Android中通过编程方式加载Vector Drawable,可使用AppCompatResources.getDrawable()类或ContextCompat.getDrawable()方法。在Jetpack Compose的现代项目中,位图和向量Drawable通过painterResource加载,它会自动检测资源格式。
import androidx.appcompat.content.res.AppCompatResources
val vectorDrawable = AppCompatResources.getDrawable(
context,
R.drawable.ic_arrow_back
)
// Jetpack Compose
Icon(
painter = painterResource(R.drawable.ic_arrow_back),
contentDescription = "Back",
tint = MaterialTheme.colorScheme.onSurface
)
使用AppCompatResources.getDrawable()时,AppCompat库会根据API级别自动选择合适的drawable版本:在Android 5.0(API 21)之前的设备上可以使用位图备用版本(fallback),在较新的设备上则使用Vector Drawable。在Jetpack Compose中,painterResource自动处理这种兼容性。
常见问题
Vector Drawable从Android 5.0(API 21)开始原生支持。对于更早的版本,必须使用AppCompat库(向量资源通过它在API 7+的设备上工作)。同时,在build.gradle中需要设置vectorDrawables.useSupportLibrary = true标志。
可以,Jetpack Compose通过painterResource()函数支持Vector Drawable。Icon组件会自动从rs/drawable/加载向量资源,并为tint应用Material主题。向量可以无损地缩放到通过modifier参数指定的任意尺寸。
SVG是一种通用的网络标准,拥有丰富的功能(过滤器、蒙版、内置样式)。Vector Drawable是针对Android进行了适配的版本,包含有限的SVG指令子集。Android不直接支持SVG,只支持通过Android Studio Asset Studio中SVG生成的Vector Drawable。
最简单的方法是使用Android Studio:右键点击吗2drawable文件夹 → New → Vector Asset → Import local SVG file。工具会自动优化SVG并生成XML Vector Drawable。另一种选择是使用在线转换器,例如SVG2VectorDrawable或支持动画导出的ShapeShifter。
问题通常与缺少AppCompat支持有关。确保在build.gradle中设置了vectorDrawables.useSupportLibrary = true标志,并使用了AppCompatDelegate。同时检查Vector Drawable是否包含所使用的AppCompat库版本中不可用的功能。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。