如何玩转Android矢量图VectorDrawable

从5.0(API等级21)开始,android开始支持矢量图了。关于什么是矢量图以及矢量图有什么优缺点不在本文的涉及范围之内,具体可以参考矢量图百科。不过这里要提一下它的优点:

保存最少的信息,文件大小比位图要小,并且文件大小与物体的大小无关
任意放大矢量图形,不会丢失细节或影响清晰度,因为矢量图形是与分辨率无关的。

从以上两个优点来看,在项目中使用矢量图至少可以缩小我们apk包的尺寸,而且可以在屏幕适配时提供很大的方便,因为矢量图是分辨率无关的。

前面也说了,矢量图从21才开始支持。那么如果我想往下兼容改怎么办呢?这个问题要放在以前的话,我会说github下就有你要的答案。但现在我不会这么说,因为前段时间Google升级了support library,官方向后兼容了矢量图的使用。要问兼容到哪个版本,我告诉你矢量图兼容到API7,矢量图动画兼容到API11(是不是已经满足了你的使用)。

好了,下面我们就来说说怎么在项目中使用矢量图。

一、VectorDrawable的使用
按照官方的说法,要在低版本上使用矢量图,需要在项目中引入新的兼容库support-vector-drawable,并且appcompat-v7库的版本要在23.2.0+(写文章这会23.2.1已经发布了)。而且你还要修改下gradle的相关配置,不要让gradle在构建的时候为你在低版本(API21以下)的情况下生成针对于不同密度的png文件,因为android studio1.4的时候支持了矢量图。

修改appcompat-v7的版本
compile 'com.android.support:appcompat-v7:23.2.0'
NOTE: 这里我只引入了23.2.0版本的appcompat-v7库,同步gradle后就编译出了support-vector-drawable-23.2.0和animated-vector-drawable-23.2.0这两个库。

修改gradle配置文件
如果你的gradle插件的版本为2.0以下,你应该这么修改

android {
 defaultConfig {
  // 不让gradle自动生成不同屏幕分辨率的png图
  generatedDensities = []
 }

 aaptOptions {
  additionalParameters "--no-version-vectors"
 }
}

如果你的gradle插件版本是2.0+,你 应该这么修改

android {
 defaultConfig {
  vectorDrawables.useSupportLibrary = true
 }
}

经过上面这几步的修改,你就可以在项目中使用矢量图了。那么,下面我们就正式来说说怎么使用。

android studio为我们提供了一个Vector Asset Studio的工具,让我么可以从material icon和svg文件生成矢量图。具体用法可以参考官方的说明文档,这里就不多说了。

Android中矢量图是以xml文档的形式存在的,像下面这样就定义了一个矢量图,里面包含了关于该矢量图的数据信息。

<!-- res/drawable/heart.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:width="24dp"
  android:height="24dp"
  android:viewportHeight="24.0"
  android:viewportWidth="24.0">
  <path
    android:fillColor="#FF000000"
    android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM15.5,11c0.83,0 1.5,-0.67 1.5,-1.5S16.33,8 15.5,8 14,8.67 14,9.5s0.67,1.5 1.5,1.5zM8.5,11c0.83,0 1.5,-0.67 1.5,-1.5S9.33,8 8.5,8 7,8.67 7,9.5 7.67,11 8.5,11zM12,17.5c2.33,0 4.31,-1.46 5.11,-3.5L6.89,14c0.8,2.04 2.78,3.5 5.11,3.5z" />
</vector>

这是我通过material icon生成的,它在android中对应着VectorDrawable这个类,也就是兼容包中的VectorDrawableCompat这个类。

定义好矢量图形后,我们就可以向普通的图形那样来使用它了。不过有几点需要注意:

*使用android:src属性的地方需要替换为app:srcCompat属性

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.damon.vectordrawabledemo.MainActivity">

  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_mood_black_24dp" />
</RelativeLayout>

*在非src属性的地方使用矢量图时,需要将矢量图用drawable容器(如StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, 和RotateDrawable)包裹起来使用。否则会在低版本的情况下报错。
而在代码中的使用和普通的png图没什么区别,调用的是同样的API。

这样我们就把矢量图引入到我们的项目中了,下面我贴几张图来对比下矢量图和png图的不同,以此来展示下矢量图的优点。

首先是png的原图和放大图

其次是矢量图的原图和放大图

对比一目了然。而且矢量图的xml的大小只有655个字节,而不同分辨率的png的大小加起来有好几k。矢量图只需要维护一个xml,而png需要维护多个图形资源。

矢量图xml文件支持的标签以及属性可以参考这里,包括了常见的填充、描边、着色等。

二、使用矢量图制作动画
23.2的支持库同样也放出了矢量图动画对应的兼容版本AnimatedVectorDrawableCompat,对应的兼容包是animated-vector-drawable,xml标签则是animated-vector。AnimatedVectorDrawableCompat能够以属性动画的形式来驱动VectorDrawable实现动画,具体来说需要分三步走:

*定义一个VectorDrawableCompat的xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
  <!-- 图片本身的大小 -->
  android:width="500px"
  android:height="500px"
  <!-- 画布的大小 -->
  android:viewportHeight="500"
  android:viewportWidth="500">
  <!-- 用来把多个path或者subgroup组合起来,group提供了一些属性比如旋转、缩放、平移。这些属性值得变化会反应在它内部的path和subgroup元素上-->
  <group
    android:scaleX="5.0"
    android:scaleY="5.0">
    <!-- 这里group和path有一个name属性,这个属性用来在使用动画时指定动画要驱动的对象 -->
    <path
      android:name="star"
      android:pathData="M 50.0,90.0 L 82.9193546357,27.2774101308 L 12.5993502926,35.8158045183 L 59.5726265715,88.837672697 L 76.5249063296,20.0595700732 L 10.2916450361,45.1785327898 L 68.5889268818,85.4182410261 L 68.5889268818,14.5817589739 L 10.2916450361,54.8214672102 L 76.5249063296,79.9404299268 L 59.5726265715,11.162327303 L 12.5993502926,64.1841954817 L 82.9193546357,72.7225898692 L 50.0,10.0 L 17.0806453643,72.7225898692 L 87.4006497074,64.1841954817 L 40.4273734285,11.162327303 L 23.4750936704,79.9404299268 L 89.7083549639,54.8214672102 L 31.4110731182,14.5817589739 L 31.4110731182,85.4182410261 L 89.7083549639,45.1785327898 L 23.4750936704,20.0595700732 L 40.4273734285,88.837672697 L 87.4006497074,35.8158045183 L 17.0806453643,27.2774101308 L 50.0,90.0Z"
      android:strokeColor="@color/colorAccent"
      android:strokeWidth="2" />
  </group>
</vector>

*定义AnimatedVectorDrawableCompat的xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vector_drawable">
  <target
    android:name="star"
    android:animation="@animator/star_anim" />
</animated-vector>

可以看到,根元素是animated-vector,并且有一个必须的属性android:drawable用来指定要驱动的矢量图对象。子标签target一方面用来指定要驱动的矢量图内的group和path的名称(这里和VectorDrawableCompat的xml中的group和path名称对应);另一方面指定要使用哪个属性动画来驱动group和path的属性进行变化来产生动画效果。

*创建属性动画
驱动trimPathStart和strokeColor属性的动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
  <objectAnimator
    android:duration="5000"
    android:propertyName="trimPathStart"
    android:repeatCount="infinite"
    android:repeatMode="restart"
    android:valueFrom="1"
    android:valueTo="0" />
  <objectAnimator
    android:duration="5000"
    android:propertyName="strokeColor"
    android:repeatCount="infinite"
    android:repeatMode="restart"
    android:valueFrom="@color/colorAccent"
    android:valueTo="@color/colorPrimaryDark" />
</set>

这样,准备工作就做好了。我们就可以使用矢量图动画了。把ImageView的src更改为矢量图动画

 <ImageView
    android:id="@+id/image_view"
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:srcCompat="@drawable/vector_drawable_anim" />

在Java代码中启动动画

 ImageView imageView = (ImageView) findViewById(R.id.image_view);
Drawable drawable = imageView.getDrawable();
//AnimatedVectorDrawableCompat实现了Animatable接口
if (drawable instanceof Animatable){
  ((Animatable) drawable).start();
}

这样就实现了矢量图动画,看看效果图吧。

好了,关于矢量图以及矢量图动画的使用就说这么多。具体的一些细节以及xml中的其他属性啥的怎么使用可以参考官方文档,自己亲自试一试就会很明了了。

文/DamonZh(简书作者)
原文链接:http://www.jianshu.com/p/456df1434739

(0)

相关推荐

  • Android 中API之Drawable资源详解及简单实例

    Android 中API之Drawable资源 1.最常用的StateListDrawable 说StateListDrawable,很多Android猿可能感到不太熟悉,不过如果说selector选择器,肯定都会恍然大悟,不错,这两个东西就是同一个~~ 它的用途之广,每个app必用,下面就写一个demo,来简要说一下用法. 比如一个登陆界面,它的输入框在获取焦点时需要更改背景,登陆按钮在输入框中有内容时,则更改背景颜色,这时候用selector选择器,那就方便多了,效果如下: EditText

  • Android编程中TextView宽度过大导致Drawable无法居中问题解决方法

    本文实例讲述了Android编程中TextView宽度过大导致Drawable无法居中问题解决方法.分享给大家供大家参考,具体如下: 在做项目的时候,很多时候我们都要用到文字和图片一起显示,一般设置TextView的DrawableLeft.DrawableRight.DrawableTop.DrawableBottom就行了.但是有一种情况是当TextView的熟悉是fill_parent或者使用权重的时候并且设置了起Gravity的ceter的时候,Drawable图片是无法一起居中的,为了

  • Android DrawableTextView图片文字居中显示实例

    在我们开发中,TextView设置Android:drawableLeft一定使用的非常多,但Drawable和Text同时居中显示可能不好控制,有没有好的办法解决呢? 小编的方案是通过自定义TextView实现. 实现的效果图: 注:第一行为原生TextView添加android:drawableLeft 第二行为自定义TextView实现的效果. 实现思路: 继承TextView,覆盖onDraw(Canvas canvas),在onDraw中先将canvas进行translate平移,再调

  • Android setButtonDrawable()的兼容问题解决办法

    Android  setButtonDrawable()的兼容问题解决办法 setButtonDrawable()的兼容问题 API16实现 /** * Set the background to a given Drawable, identified by its resource id. * * @param resid the resource id of the drawable to use as the background */ public void setButtonDraw

  • Android 让自定义TextView的drawableLeft与文本一起居中

    前言 TextView的drawableLeft.drawableRight和drawableTop是一个常用.好用的属性,可以在文本的上下左右放置一个图片,而不使用更加复杂布局就能达到,我也常常喜欢用RadioButton的这几个属性实现很多效果,但是苦于不支持让drawbleLeft与文本一起居中,设置gravity为center也无济于事,终于有空研究了一下,这里与大家一起分享. 正文 一.效果图  二.实现代码 自定义控件 /** * drawableLeft与文本一起居中显示 * *

  • 关于Android中drawable必知的一些规则

    前言 一入 Android 深似海,相信很多 Android 开发者深有体会,Android 系统版本的碎片化,Android 硬件设备的多样性,第三方 Rom 的不确定因素.现在想开发一个合格的商业化 App 真的不容易,先不说别的,应用的兼容性就是一项技术和耐心的双重考验,想完美适配各种情况可以说是不可能的,往往都是在人力和适配率之间寻找平衡,今天要说的 drawable 就是需要适配的一个重要角色. 配置限定符 对于不同的屏幕密度.不同的设备方向,不同的语言和区域,都会涉及到备选 draw

  • Android App开发中将View或Drawable转为Bitmap的方法

    View转换为Bitmap Android中经常会遇到把View转换为Bitmap的情形,比如,对整个屏幕视图进行截屏并生成图片:Coverflow中需要把一页一页的view转换为Bitmap.以便实现复杂的图形效果(阴影.倒影效果等):再比如一些动态的实时View为便于观察和记录数据.需要临时生成静态的Bitmap. 实现方法: 1)下面是笔者经常用的一个转换方法 public static Bitmap convertViewToBitmap(View view, int bitmapWid

  • android中图形图像处理之drawable用法分析

    本文实例讲述了android中图形图像处理之drawable用法.分享给大家供大家参考.具体如下: 一.如何获取 res 中的资源 数据包package:android.content.res 主要类:Resources 其主要接口按照功能,划分为以下三部分: getXXXX() 例如: int getColor(int id) Drawable getDrawable(int id) String getString(int id)  直接获取res中存放的资源 InputStream ope

  • Android中EditText的drawableRight属性设置点击事件

    这个方法是通用的,不仅仅适用于EditText,也适用于TextView.AutoCompleteTextView等控件. Google官方API并没有给出一个直接的方法用来设置右边图片的点击事件,所以这里我们需要通过点击位置来判断点击事件,效果如图: 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.a

  • 如何玩转Android矢量图VectorDrawable

    从5.0(API等级21)开始,android开始支持矢量图了.关于什么是矢量图以及矢量图有什么优缺点不在本文的涉及范围之内,具体可以参考矢量图百科.不过这里要提一下它的优点: 保存最少的信息,文件大小比位图要小,并且文件大小与物体的大小无关 任意放大矢量图形,不会丢失细节或影响清晰度,因为矢量图形是与分辨率无关的. 从以上两个优点来看,在项目中使用矢量图至少可以缩小我们apk包的尺寸,而且可以在屏幕适配时提供很大的方便,因为矢量图是分辨率无关的. 前面也说了,矢量图从21才开始支持.那么如果我

  • Android矢量图之VectorDrawable类自由填充色彩

    2014年6月26日的I/O 2014开发者大会上谷歌正式推出了Android L,它带来了全新的设计语言Material Design,新的API也提供了这个类VectorDrawable .也就是android支持SVG类型的资源也就是矢量图.想到矢量图,自然就会想到位图,何为矢量图,何为位图?先来说说位图吧,我们经常用的png,jpg就是位图了,他是由一个单元一个单元的像素组成的.当小icon遇到大屏幕手机的时候,icon如果被撑开那就是马赛克一样啦.这可不是我们想要的.而矢量图正式和它相

  • Android三种方式生成矢量图之VectorDrawable类使用详解

    目录 生成矢量图VectorDrawable的三种方式 静态VectorDrawable的使用 配置引用和参数 在控件中使用 生成矢量图VectorDrawable的三种方式 第一种: 选中drawable文件夹,右键New --> Vector Asset --> 选中Clip Art ,在这里面可以选择一些矢量图 ,点击Next,然后 Finish即可. 第二种:(前提:自己有一张svg或psd的图片) 选中drawable文件夹,右键New --> Vector Asset --&

  • Android动态使用VectorDrawable过程详解

    目录 导言 案例演示 问题解决 接上篇继续,讲解使用动态的VectorDrawable 上篇链接: Android三种方式生成矢量图之VectorDrawable类使用详解 导言 VectorDrawable有两个优点,一个是缩放不失真,另一个是使PNG的体积,大幅度减小,那么如果仅仅只有这两个优点,其实我是并不需要使用VectorDrawable,或者说,这并不能成为我们使用VectorDrawable的重要原因. 那我们使用它的重要原因是什么呢? 那就是VectorDrawable可以使用动

  • Android 矢量室内地图开发实例

    矢量室内地图开发 因为公司项目的需要,需要开发一套室内地图,并实现路线的规划功能.因为之前没做过这方面的开发,相关的资料也比较少,所以只能一个人去摸索.刚开始我是使用一般的位图去当作的地图,但是这个也让我在后面吃了不少的苦头. 我们知道地图一般都会有缩放和拖拽等功能,正当我把一样利用位图开发的地图样例时,我发现了不少的问题: 1.位图缩放会失真: 2.图片加载比较慢: 3.会导致客户端内存溢出 ... 因为这些问题,我不得不放弃这种方法.要解决上面的问题只能使用矢量图进行开发了,于是我使用了HT

  • iOS应用开发中矢量图的使用及修改矢量图颜色的方法

    之前捣鼓了点东西,要适配6和Plus,自己做做切图才发现确实有够烦.基于矢量图生成PNG图形的方法也是事后才知道,学习下,希望接下来可以实践.下面进入译文. iOS应用的视觉形式通常是以图形元素驱动的.在设计开发一款应用时,你需要不同规格的应用图标,例如不同尺寸的Default.png图片,同时还需要为UI的实现准备@1x和@2x图形资源.所有这些图形元素都会让你的产品看上去更吸引人,但弊端也是很明显的 - 你需要为每种规格的图形元素单独切图.而随着iPhone 6及Plus的发布,我们又多了一

  • 微信多图上传解决android多图上传失败问题

    微信提供了文件上传的方法wx.uploadFile来上传我们的图片 wx.chooseImage({ success: function(res) { var tempFilePaths = res.tempFilePaths wx.uploadFile({ url: 'http://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址 filePath: tempFilePaths[0], name: 'file', formData:{ 'user':

  • Jupyter Notebook输出矢量图实例

    相信大家都很熟悉在 Jupyter Notebook 上面用 Matplotlib 了,但是不知道大家看到画出来那一坨糊糊的东西会不会跟我一样浑身难受.实际上,只要多加一行配置,就能够让 Matplotlib 在 Jupyter Notebook 上面输出矢量图了: import matplotlib import matplotlib.pyplot as plt %matplotlib inline %config InlineBackend.figure_format = 'svg' 上面的

  • Android 多图上传后将图片进行九宫格展示的实例代码

    不多说上代码 public abstract class NineGridAdapter { protected Context context; protected List list; public NineGridAdapter(Context context, List list) { this.context = context; this.list = list; } public abstract int getCount(); public abstract String get

  • python将图片转为矢量图的方法步骤

    本文主要介绍了python图片转为矢量图,分享给大家,具体如下: import numpy as np import matplotlib.pyplot as plt import cv2 fig, ax = plt.subplots() plt.figure(1) image=cv2.imread("2.jpg") # you can specify the marker size two ways directly: # 这样一个一个像素太慢了故而要将同样颜色的坐标进行分类处理 c

随机推荐