什么是svg
SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics)。其他图像格式都是基于像素处理的,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。
位图vs矢量图
位图
比如png等,是由像素点构成的图像,对于不同的屏幕需要不同的适配,同一张图片在不同屏幕上可能会失真。
Android系统在使用png等位图时如下图:

会将不同dpi的图片先经过解码之后再绘制显示在屏幕上。
矢量图
矢量图是用xml文件来存放图片绘制的矢量信息,可以适配不同的屏幕,不会因为拉伸等导致图片失真。

Android中svg中的过程如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GlFmCdLG-1691499986208)(https://tech-proxy.bytedance.net/tos/images/1691499961169_15b778593f5d72d21a356436b6715a1e)]](https://img-blog.csdnimg.cn/f7f6632fe912455c87d87fe82feddd14.png)
svg结构
svg保存在xml文件里面,是一棵树如下图:

一个简单的svg对应的xml如下所示:
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20" tools:ignore="MissingDefaultResource"> <path android:pathData="M19.3188,18.0273L13.232,11.9406C14.1766,10.7195 14.6875,9.2266 14.6875,7.6563C14.6875,5.7766 13.9539,4.0141 12.6273,2.6852C11.3008,1.3563 9.5336,0.625 7.6563,0.625C5.7789,0.625 4.0117,1.3586 2.6852,2.6852C1.3563,4.0117 0.625,5.7766 0.625,7.6563C0.625,9.5336 1.3586,11.3008 2.6852,12.6273C4.0117,13.9563 5.7766,14.6875 7.6563,14.6875C9.2266,14.6875 10.7172,14.1766 11.9383,13.2344L18.025,19.3188C18.1,19.3938 18.2219,19.3938 18.2969,19.3188L19.3188,18.2992C19.3938,18.2242 19.3938,18.1023 19.3188,18.0273ZM11.3687,11.3687C10.375,12.3602 9.0578,12.9062 7.6563,12.9062C6.2547,12.9062 4.9375,12.3602 3.9437,11.3687C2.9523,10.375 2.4063,9.0578 2.4063,7.6563C2.4063,6.2547 2.9523,4.9352 3.9437,3.9437C4.9375,2.9523 6.2547,2.4063 7.6563,2.4063C9.0578,2.4063 10.3773,2.95 11.3687,3.9437C12.3602,4.9375 12.9062,6.2547 12.9062,7.6563C12.9062,9.0578 12.3602,10.3773 11.3687,11.3687Z" android:fillColor="#1F2329" android:fillType="evenOdd"/> </vector>
讯享网
上面xml中
1、path对应路径
2、M代表移动画笔到对应的坐标 (move)
3、L代表直线(line)
4、C代表绘制曲线(curve)
5、A代表弧线(Arc)
6、Z表示结束(close)
Android 中使用svg
项目配置
在app的build.gradle文件的defaultConfig中添加vectorDrawables.useSupportLibrary = true如下:
讯享网android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
图片所在module的build.gradle中也添加上
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
图片导入
figma上一些小的图片可以下载svg格式:

在Android studio按下面方式进行导入

导入后会自动生成xml文件
search.xml
讯享网<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20" tools:ignore="MissingDefaultResource"> <path android:pathData="M19.3188,18.0273L13.232,11.9406C14.1766,10.7195 14.6875,9.2266 14.6875,7.6563C14.6875,5.7766 13.9539,4.0141 12.6273,2.6852C11.3008,1.3563 9.5336,0.625 7.6563,0.625C5.7789,0.625 4.0117,1.3586 2.6852,2.6852C1.3563,4.0117 0.625,5.7766 0.625,7.6563C0.625,9.5336 1.3586,11.3008 2.6852,12.6273C4.0117,13.9563 5.7766,14.6875 7.6563,14.6875C9.2266,14.6875 10.7172,14.1766 11.9383,13.2344L18.025,19.3188C18.1,19.3938 18.2219,19.3938 18.2969,19.3188L19.3188,18.2992C19.3938,18.2242 19.3938,18.1023 19.3188,18.0273ZM11.3687,11.3687C10.375,12.3602 9.0578,12.9062 7.6563,12.9062C6.2547,12.9062 4.9375,12.3602 3.9437,11.3687C2.9523,10.375 2.4063,9.0578 2.4063,7.6563C2.4063,6.2547 2.9523,4.9352 3.9437,3.9437C4.9375,2.9523 6.2547,2.4063 7.6563,2.4063C9.0578,2.4063 10.3773,2.95 11.3687,3.9437C12.3602,4.9375 12.9062,6.2547 12.9062,7.6563C12.9062,9.0578 12.3602,10.3773 11.3687,11.3687Z" android:fillColor="#1F2329" android:fillType="evenOdd"/> </vector>
在布局中引用
<ImageView android:id="@+id/Search" android:layout_width="@dimen/size_24_dp" android:layout_height="@dimen/size_24_dp" android:layout_marginEnd="@dimen/size_14_dp" android:src="@drawable/search" />
修改svg图片颜色
有时候设计给的图片一样但是颜色不同,如果每一个颜色svg都导入会增加包大小,可以通过在引用svg的xml中通过tint设置svg图片的颜色。
讯享网<ImageView android:id="@+id/Search" android:layout_width="@dimen/size_24_dp" android:layout_height="@dimen/size_24_dp" android:layout_marginEnd="@dimen/size_14_dp" android:src="@drawable/search" app:tint="@color/c_00B8E5" />

svg图片添加点击态
有时候需要根据不同状态显示不同颜色,svg中可以实现这种功能,首先定义一个color类型的selector。在res目录下创建一个color的文件夹,然后创建search_selector.xml如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/c_00B8E5" android:state_pressed="true" /> <item android:color="@color/black" /> </selector>
在需要点击态的xml中通过tint来控制颜色变化
讯享网<ImageView android:id="@+id/Search" android:layout_width="@dimen/size_24_dp" android:layout_height="@dimen/size_24_dp" android:clickable="true" android:focusable="true" android:src="@drawable/search" app:tint="@color/search_selector" />

svg使用优化
在 api level 21以上使用svg默认情况下
1、会在drawable-anydpi-v24中生成seach.xml文件

search.xml的大小为673B

2、会在drawable-xxhdpi-v4中生成seach.png文件

search.png的大小为1.2kB
由于使用svg时生成了png图片所以包大小并没有减少。一定要配置
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true } }
可以使用下面的方式使得的apk中不生成png图片,只保留svg的xml文件。
svg动画使用
如下在布局中添加svg的xml作为srcCompat
讯享网<androidx.appcompat.widget.AppCompatImageView android:id="@+id/breakHeart" android:layout_width="160dp" android:layout_height="160dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/break_heart_anim" />
其中break_heart_anim.xml是svg动画xml。
<animated-vector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" tools:targetApi="lollipop"> <aapt:attr name="android:drawable"> <vector android:name="heartbreak" android:width="56dp" android:height="56dp" android:viewportWidth="56" android:viewportHeight="56"> <group android:name="broken_heart_left_group" android:pivotX="28" android:pivotY="37.3"> <path android:name="broken_heart_left" android:pathData="M 28.031 21.054 C 28.02 21.066 28.01 21.078 28 21.09 C 26.91 19.81 25.24 19 23.5 19 C 20.42 19 18 21.42 18 24.5 C 18 28.28 21.4 31.36 26.55 36.03 L 28 37.35 L 28.002 37.348 L 27.781 36.988 L 28.489 36.073 L 27.506 34.764 L 28.782 33.027 L 26.944 31.008 L 29.149 28.725 L 27.117 27.143 L 29.149 25.018 L 26.488 22.977 L 28.031 21.054 L 28.031 21.054 Z" android:fillColor="#ff0000"/> </group> ... </vector> </aapt:attr> <target android:name="broken_heart_left_group"> <aapt:attr name="android:animation"> <objectAnimator android:propertyName="rotation" android:duration="400" android:valueFrom="0" android:valueTo="-20" android:valueType="floatType" android:interpolator="@android:interpolator/linear_out_slow_in"/> </aapt:attr> </target> </animated-vector>
在代码中使用下面方式开启动画
讯享网breakHeart.setOnClickListener { if (breakHeart.drawable is AnimatedVectorDrawable) { (breakHeart.drawable as AnimatedVectorDrawable).start() } }
动画效果如下

svg优点
1、svg比png,webp等小。


可以看到上面png和xml的大小对比,使用png大小差不多是xml的一倍。
2、svg放大不会失真

svg缺点
svg不支持硬件加速,所以渲染速度比png慢,下图是微信的数据对比


SVG在加载的过程中得到非常大优势,而Draw的时候因为没有硬件渲染导致性能远不如PNG。但通过在加载阶段的大幅提升,让SVG在整体耗时上赢了PNG。
svg兼容性

Android 4.4(API level 20)及以下版本,有两种解决方案 :
① 将矢量图生成为 PNG 图片 ;
② 使用 23.2 及以上版本的支持库 ;
在app的build.gradle文件中添加:
android { defaultConfig { generatedDensities = ['xhdpi', 'xxhdpi'] } }
Android 5.0(API level 21)及以上版本,可以直接使用vector.xml文件,不需要将vector.xml文件转换成png。但是需要在build.gradle中添加
讯享网android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
svg批量转换工具
https://github.com/MegatronKing/SVG-Android/tree/master/svg-vector-cli
使用方法
command line introductions [-d/-dir] the target svg directory [-f/-file] the target svg file [-o/output] the output vector file or directory [-w/width] the width size of target vector image [-h/height] the height size of target vector image command line samples java -jar svg2vector-cli.jar -d D:\svg or java -jar svg2vector-cli.jar -f D:\svg\icon_facebook.svg or java -jar svg2vector-cli.jar -d D:\svg -o D:\vector or java -jar svg2vector-cli.jar -f D:\svg\icon_facebook.svg -o D:\vector\icon_facebook.xml or java -jar svg2vector-cli.jar -d D:\svg -o D:\vector -w 24 -h 24 or java -jar svg2vector-cli.jar -f D:\svg\icon_facebook.svg -o D:\vector\icon_facebook.xml -w 24 -h 24
todo:
tint修改的是fillColor有些情况下点击态只需要修改strokeColor不需要修改fillColor
讯享网android:fillColor="#ffffff" android:strokeColor="#2A97B9"/>
参考
1、https://developer.mozilla.org/en-US/docs/Web/SVG
2、https://developer.android.com/studio/write/vector-asset-studio
3、https://www.androidhive.info/2017/02/android-working-svg-vector-drawables/
4、https://developer.android.com/topic/libraries/support-library/packages?hl=zh-cn
5、https://www.growfox.co.uk/blog/5-reasons-you-should-be-using-svgs-over-pngs
6、https://mp.weixin..com/s?__biz=MzAwNDY1ODY2OQ==&mid=&idx=1&sn=3d7b07d528f38e9f812e8df7df1e3322&scene=4#wechat_redirect
4、https://medium.com/android-dev-hacks/android-vector-drawables-bfb515ba8f2e
5、https://tech.bytedance.net/articles/11584

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/28104.html