svg代码怎么用

什么是svg SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics)。其他图像格式都是基于像素处理的,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。 位图vs矢量图 位图

什么是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)]

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.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207863967&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

知秋君
上一篇 2024-08-25 08:12
下一篇 2024-08-25 07:48

相关推荐