持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
在上篇文章中,我们学习了 Android 中 SVG 的基本语法。本篇文章来学习一下高级一点的用法:使用 SVG 绘制渐变色和圆形。
一、渐变色的绘制
一张最简单的渐变色 SVG 图片代码如下:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<path android:pathData="M0,0 H100 V100 H-100z">
<aapt:attr name="android:fillColor">
<gradient
android:startColor="#FFFFFF"
android:endColor="#000000"
android:startX="0"
android:startY="0"
android:endX="100"
android:endY="100"
android:type="linear" />
</aapt:attr>
</path>
</vector>
效果图:
通过 aapt:attr 指定需要注入属性,name 指定注入的属性名,这里设置为 android:fillColor,表示需要注入的属性是填充色。
然后编写 gradient 标签,设置开始颜色 startColor,结束颜色 endColor,这里指定为从白色到黑色。
然后设置起始点和终点的坐标,这里定义的是从 (0,0) 到 (100,100),也就是从画布左上角到右下角,这条路径的含义是渐变色的变化方向。
为了更清晰地解释渐变色的方向,不妨将起始点和终点修改为 (0,0) 到 (0,100),也就是将这里的 endX 改为 0,效果如下:
可以很明显的看出,渐变色的方向由左上到左下变成了从上到下,这就是渐变色方向的含义。
type 属性用于指定渐变色的渐变类型,常用的类型有 linear、radial、sweep,分别表示线型、发散型、扫描型。
如果渐变色只能指定 startColor、endColor,那就只能处理两种颜色之间的渐变,那么多色渐变做起来就会很复杂。所以还有另一种方式指定渐变色的颜色变化,就是给 gradient 标签内部添加 item 标签:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<path android:pathData="M0,0 H100 V100 H-100z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="0"
android:startY="0"
android:endX="100"
android:endY="100"
android:type="linear">
<item
android:color="#FFFFFF"
android:offset="0" />
<item
android:color="#0000FF"
android:offset="0.5" />
<item
android:color="#000000"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</vector>
效果如下:
每个 item 标签代表一种颜色,offset 表示这个颜色处于整个渐变区域的哪个位置。取值范围是 0~1,表示整个渐变区域的百分比。
在设置了 item 之后,startColor 和 endColor 就不会起作用了。也就是说 startColor/endColor 和 item 标签是不能混用的。
通过 item 标签,我们将 offset 0 的区域指定为 白色,offset 0.5 的区域指定为蓝色,offset 1 的区域指定为 黑色,就形成了上图中的效果。
再看一个发散型渐变色的例子:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<path android:pathData="M0,0 H100 V100 H-100z">
<aapt:attr name="android:fillColor">
<gradient
android:startColor="#FFFFFF"
android:endColor="#000000"
android:centerX="50"
android:centerY="50"
android:gradientRadius="50"
android:type="radial" />
</aapt:attr>
</path>
</vector>
效果图:
是不是有种黑洞照片的科幻感 =,=
在这个例子中,type 指定为 radial,表示发散型渐变色。发散型渐变色需要的参数和线型渐变色的参数略有不同。
startColor 和 endColor 表示起始颜色和结束颜色,这一点和线型渐变色是相同的。并且,同样可以通过 item 标签指定多种渐变色。
然后通过 centerX、centerY 指定圆心的坐标,通过 gradientRadius 指定渐变色的半径。这样就能完成上图的效果。
接下来再看一个扫描型渐变色的例子:
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<path android:pathData="M0,0 H100 V100 H-100z">
<aapt:attr name="android:fillColor">
<gradient
android:startColor="#FFFFFF"
android:endColor="#000000"
android:centerX="50"
android:centerY="50"
android:type="sweep">
</gradient>
</aapt:attr>
</path>
</vector>
效果图:
在这个例子中,type 指定为 sweep,表示扫描型渐变色。可以看到,扫描型渐变色和发散型渐变色的写法比较类似。
同样地,startColor 和 endColor 表示起始颜色和结束颜色。并且,也可以通过 item 标签指定多种渐变色。
然后再通过 centerX、centerY 指定圆心的坐标即可。
注:线型、射线型、扫描型的名字是我自己翻译的,我没有找到这三种渐变色类型的官方中文译名。建议读者直接使用英文名交流 linear、radial、sweep。
再注:在 Android Studio 中编辑渐变色时,没有代码提示、自动补全的功能,我暂时没有找到解决办法,只能手打一个个属性。
二、圆形的绘制
一个最简单的圆形的代码是:
<path
android:fillColor="#FFFFFF"
android:pathData="
M100,100
A30,30,0,1,0,99,100
z" />
效果图:
圆形的绘制使用的是 A 符号,前文中讲过,A 是用来绘制弧线的(arc)。在 SVG 中,并没有专门用于绘制圆形的符号。所以要么通过一条几乎闭合的弧线绘制圆形、要么用两条弧线绘制圆形。
读者可能会有疑问,为什么说是几乎闭合呢?如果将弧线的起点和终点设置成一样,不就能绘制一条完整的圆形了吗?
实际上 A 符号的起点和终点一样时,不会触发 SVG 的绘制。这可能是个 bug,(产品经理小声说道:这其实是个 feature)。或许 A 符号出于安全检查的考虑,为了避免做无用的绘制,将起点和终点一致的弧线直接忽略了。
所以这里的 pathData 中,先移动到 (100,100) 坐标准备绘制,而弧线的终点坐标是 (99,100),终点和起点的横坐标相差 1,目的就是避免 A 符号不触发绘制。所以这里的圆严格意义上来讲不是一个正圆,但肉眼是分辨不出来的。
如果用两条弧线绘制圆形的话,可以保证绘制出的是一个正圆,具体方法是每条弧线只画一个半圆,最后拼接成一个正圆。这种方式稍显复杂,所以我没有采用。
小结
本文学习了三种渐变色的绘制:linear、radial、sweep。以及 A 符号绘制圆形的技巧。
参考文章
Android矢量图(一)--VectorDrawable基础