Android SVG

SVG 图像技术(Scalable Vector Graphics ,可缩放的矢量图形)是目前较为新颖的图像文件格式,基于 XML 框架,具有以下优势。

  • 无损的扩展分辨率
  • 文件体积小
  • 支持动画

在 Android 系统中, SVG 图像技术的实现方式是 Vector 图像,我们在写应用时用到的很多 .png 格式的图标通常都要准备两个高低分辨率的图片,这是使用 SVG 图像则可有效的缩小应用的体积。下面看看如何使用和生成 Vector 图像。

SVG 图片

  1. 获取 .svg 格式的图像文件,这里推荐一个图标网站 阿里巴巴矢量图标库
  2. 创建图像,在 Android Studio 中,依次选择:【 file 】/【 New 】/【 Vector Asset 】,勾选 Local file 并在电脑本地选择下载好的文件。
  1. 设置进布局代码中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/ic_milky" />

</LinearLayout>

可以看到图像文件被生成了 ic_milky.xml 代码

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:viewportWidth="1024"
    android:viewportHeight="1024">
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M758.6,344.6C742.4,226.7 641.4,135.9 519,135.9s-223.4,90.8 -239.6,208.7h479.2z" />
    <path
        android:fillColor="#E5E5E5"
        android:pathData="M519.1,135.9c-12.2,0 -24.1,0.9 -35.8,2.6 104.7,16.6 187,100.3 201.4,205.7H279.6c0,0.1 0,0.2 -0.1,0.4h479.1c-16.1,-117.9 -117.2,-208.7 -239.5,-208.7zM226,344.9h582.2v89.6H226z" />
    <path
        android:fillColor="#FF954D"
        android:pathData="M295,580.1s41.4,-11.8 92.2,-15.2c8.4,-0.6 17.1,-0.9 25.9,-0.9 61.8,0 158.5,35.8 212.3,35.8 10.1,0 20.3,-0.6 30.3,-1.6 43.3,-4.4 81.9,-16.1 81.9,-16.1h-0.1l-47,327.8c-2.2,15.5 -15.5,27 -31.2,27H373.4c-15.7,0 -28.9,-11.5 -31.1,-27l-47.6,-329.4" />
    <path
        android:fillColor="#FF6545"
        android:pathData="M655.6,598.2c-2.7,0.3 -5.5,0.5 -8.3,0.7L613.4,835c-2.2,15.5 -15.5,27 -31.2,27H335.4l6.9,47.9c2.2,15.5 15.5,27 31.1,27h285.8c15.7,0 28.9,-11.5 31.2,-27l47,-327.7c-1.5,0.4 -39.4,11.7 -81.8,16zM737.4,582.1c0.1,0 0.1,0 0,0z" />
    <path
        android:fillColor="#333333"
        android:pathData="M656.2,960.2H370.4c-25.6,0 -47.6,-19.1 -51.2,-44.4l-31.8,-221.3c-1.6,-11.1 6.1,-21.3 17.2,-22.9 11.1,-1.6 21.3,6.1 22.9,17.2L359.3,910c0.8,5.5 5.6,9.6 11.1,9.6h285.8c5.5,0 10.3,-4.1 11.1,-9.6L710,612.3c-15.2,3.4 -34.8,7 -55.5,9.1 -11.4,1.2 -22.3,1.7 -32.3,1.7 -28.3,0 -64.9,-8.5 -103.6,-17.5 -38.8,-9 -79,-18.3 -108.6,-18.3 -7.9,0 -16.1,0.3 -24.5,0.8 -48.1,3.2 -87.5,14.3 -87.9,14.4 -1.2,0.3 -2.5,0.6 -3.7,0.7 -10.7,1 -20.4,-6.6 -21.9,-17.3l-18,-125.2h-31.7c-11.2,0 -20.3,-9.1 -20.3,-20.3V351c0,-11.2 9.1,-20.3 20.3,-20.3h34.5c11.5,-55.4 40.8,-105.8 83.7,-143.5 47.8,-42 109.2,-65.2 173,-65.2s125.2,23.1 173,65.2c42.9,37.7 72.2,88.1 83.7,143.5h34.5c11.2,0 20.3,9.1 20.3,20.3v89.6c0,11.2 -9.1,20.3 -20.3,20.3H773l-2.3,15.9c-1.6,11.1 -11.8,18.8 -22.9,17.2 -11.1,-1.6 -18.8,-11.9 -17.2,-22.9l4.8,-33.3c1.4,-10 10,-17.4 20,-17.4h29v-49.1h-31.3c-10.1,0 -18.7,-7.5 -20.1,-17.5 -14.9,-109 -109.3,-191.2 -219.5,-191.2S308.9,244.8 294,353.8c-1.4,10 -9.9,17.5 -20.1,17.5h-31.3v49.1h29c10.1,0 18.6,7.4 20,17.4l17.3,120.5c17.7,-3.8 44.2,-8.5 73.9,-10.5 9.3,-0.6 18.4,-0.9 27.2,-0.9 34.3,0 76.7,9.8 117.8,19.4 36.5,8.5 70.9,16.5 94.5,16.5 8.7,0 18.2,-0.5 28.3,-1.5 37.2,-3.8 71.1,-13.3 77.2,-15.1 3.1,-1.1 6.4,-1.4 9.7,-0.9 9.4,1.4 16.5,9.1 17.2,18.6 0.1,1.9 0,3.8 -0.4,5.6L707.4,916c-3.6,25.1 -25.6,44.2 -51.2,44.2z" />
    <path
        android:fillColor="#333333"
        android:pathData="M583.7,371.3c-4.2,0 -8.4,-1.3 -12.1,-4 -9,-6.7 -10.8,-19.4 -4.1,-28.3L746.4,98.7c3,-4 7.3,-6.7 12.1,-7.7l129.2,-26.7c11,-2.3 21.7,4.8 23.9,15.7 2.3,11 -4.8,21.7 -15.7,23.9L774.3,129 599.9,363.1c-3.9,5.4 -10,8.2 -16.2,8.2z" />
    <path
        android:fillColor="#FFA73E"
        android:pathData="M652.9,371.3H372c-11.2,0 -20.3,-9.1 -20.3,-20.3 0,-11.2 9.1,-20.3 20.3,-20.3h280.9c11.2,0 20.3,9.1 20.3,20.3 -0.1,11.2 -9.1,20.3 -20.3,20.3zM654.2,460.8H370.7c-11.2,0 -20.3,-9.1 -20.3,-20.3 0,-11.2 9.1,-20.3 20.3,-20.3h283.5c11.2,0 20.3,9.1 20.3,20.3 0,11.3 -9.1,20.3 -20.3,20.3z" />
</vector>

Vwctor 动画

使用动态图像需要最低支持库( Android Support Library )的版本达到 23.2 及以上。
Android 系统 5.0 及以上( minSdkVersion 21 )

播放 Vector 动态图像需要用到三个文件

  • 静态的图像文件 v_heard.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="256dp"
    android:height="256dp"
    android:viewportWidth="70"
    android:viewportHeight="70">
    <path
        android:name="heart1"
        android:pathData="
M58.3,10.6C51.4,3.6,40,3.7,32,10.5c-1.3-1.1-2.6-2-4.1-2.8l-5.5-3.8c-0.3-0.2-0.6-0.2-1-0.1c-0.3,0.1-0.5,0.4-0.6,0.8l-0.2,1C15,4.9,9.6,6.7,5.7,10.6C-1.8,18.1-2,30,5.4,37.8L31.3,64c0.2,0.2,0.4,0.3,0.7,0.3s0.5-0.1,0.7-0.3l25.9-26.2C65.9,30.2,65.7,18,58.3,10.6z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart2"
        android:pathData="
M57.2,36.4L32,61.8L6.8,36.4c-1-1-1.8-2.1-2.5-3.3l7.5,3.4c0.4,0.2,0.8,0.3,1.2,0.3c0.4,0,0.8-0.1,1.1-0.2l0.7,6.4c0,0.5,0.4,0.8,0.8,0.9l9.4,1.4c0,0,0.1,0,0.1,0c0.3,0,0.5-0.1,0.7-0.3c0.2-0.2,0.3-0.6,0.2-0.9l-4-17.6l13.3,11.9c0.2,0.2,0.4,0.3,0.7,0.3c0.1,0,0.2,0,0.2,0c0.3-0.1,0.6-0.3,0.7-0.6l3.2-8.9c0.2-0.4,0-0.9-0.4-1.2l-5.3-3.6c0.6-0.5,1.1-1.3,1.1-2.1l0.7-9.1c0-0.3-0.1-0.7-0.4-0.9c-0.3-0.2-0.7-0.2-1-0.1l-3.6,1.5l1.1-0.9c0,0,0,0,0,0c0,0,0,0,0,0c7.2-6.7,17.8-7,24.2-0.6C63.5,18.6,63.7,29.6,57.2,36.4z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />

    <path
        android:name="heart3"
        android:pathData="
M14.3,20.7l1.6,1.9L5.3,26.4l-0.9-9.1L14.3,20.7z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart4"
        android:pathData="
M19.5,18.3l1.5,3.8    l-2,1.2l-2.6-3.1L19.5,18.3z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart5"
        android:pathData="
M17.2,24.3C17.3,24.3,17.3,24.3,17.2,24.3l0.4,0.5L14,34c0,0,0,0,0,0l0,0c-0.1,0.3-0.3,0.5-0.5,0.6c-0.3,0.1-0.6,0.1-0.8,0l-6.8-3.1l7.6-5.9L17.2,24.3z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart6"
        android:pathData="
M22.4,23.5    l9.6,1.2l6.2,4.3l-2.5,6.8L22.2,23.7L22.4,23.5z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart7"
        android:pathData="
M33.8,21.9c0,0.3-0.2,0.6-0.4,0.7c-0.2,0.2-0.5,0.2-0.9,0.2l-9.6-1.2l-0.3-0.7    l3.3-2.8l8.4-3.6L33.8,21.9z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart8"
        android:pathData="
M30.4,11.9l-8.4,7L21,16.5c0,0,0-0.1-0.1-0.1l1.9-9.5c0,0,0.2,0,0.2,0s0,0,0,0l-0.2-0.4L30.4,11.9z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart9"
        android:pathData="
M7.1,12c3.5-3.5,8.2-5.1,13.3-4.5l-1.5,8.8l-4.1,2.4L4.5,15.3C5.3,14.1,6.1,13,7.1,12z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
    <path
        android:name="heart10"
        android:pathData="
M2.6,19.6l0.8,8.3c0,0.3,0.2,0.6,0.5,0.7c0.2,0.1,0.3,0.2,0.5,0.2c0.1,0,0.2,0,0.3-0.1l2.7-1L3.3,31c0,0,0,0,0,0C1.8,27.4,1.6,23.3,2.6,19.6z"
        android:strokeWidth="1"
        android:strokeColor="#E91E63" />
</vector>
  • 动态图像资源文件 v_heard_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/v_heard">
    <target
        android:name="heart1"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart2"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart3"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart4"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart5"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart6"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart7"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart8"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart9"
        android:animation="@animator/heart_animator" />
    <target
        android:name="heart10"
        android:animation="@animator/heart_animator" />
</animated-vector>
  • 属性动画文件 heart_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="6000"
    android:propertyName="trimPathEnd"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType"/>
  1. 布局设置静态的图片
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AnimationActivity">

    <Button
        android:id="@+id/main_b_draw"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="绘制"
        tools:ignore="HardcodedText"/>

    <ImageView
        android:id="@+id/main_iv_image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="@null"
        android:src="@drawable/v_heard"/>

</RelativeLayout>
  1. 代码设置动画,将动态图片资源文件 v_heard_animation.xml 转化为动画向量图像类 AnimatedVectorDrawable ,将图像添加至图像控件 mIvImageView,调用动态图像的 start() 方法。
public class AnimationActivity extends AppCompatActivity {
    private ImageView mIvImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animation);

        mIvImageView = findViewById(R.id.main_iv_image_view);

        animateImage();

        // 重绘动画
        findViewById(R.id.main_b_draw).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animateImage();
            }
        });
    }

    /**
     * 动画播放图片
     * 只支持5.0以上.
     */
    private void animateImage() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 获取动画效果
            AnimatedVectorDrawable mAnimatedVectorDrawable = (AnimatedVectorDrawable)
                    ContextCompat.getDrawable(getApplication(), R.drawable.v_heard_animation);
            mIvImageView.setImageDrawable(mAnimatedVectorDrawable);
            if (mAnimatedVectorDrawable != null) {
                mAnimatedVectorDrawable.start();
            }
        }
    }
}

运行效果如下。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342