Android UI:矢量图使用

一、矢量图简介
最近在进行Android App“瘦身 ”的时候,了解到矢量图(VectorDrawable)相关概念。
从Android5.0(API level 21)开始,有两个类支持矢量图:VectorDrawable和AnimatedVectorDrawable。VectorDrawable是一个矢量图,定义在一个XML文件中的点、线和曲线,和它们相关颜色的信息集合。AnimatedVectorDrawable是矢量图动画,使用多个XML文件而不是针对不同分辨率使用多个图片来实现动画。
使用矢量图主要有如下两个优:
  图片扩展性:它可以进行缩放并且不损失图片的质量,这意味着使用同一个文件对不同屏幕密度调整大小并不损失图片的质量;
  图片大小小:同样大小和内容图片下相比,矢量图比PNG图片更小,这样就能得到更小的APK文件和更少的维护工作;
然而,系统渲染VectorDrawable需要花费更多时间。因为矢量图的初始化加载会比相应的光栅图片消耗更多的CPU周期,但是两者之间的内存消耗和性能接近。因此我们可以只考虑在显示小图片的时候使用矢量图(建议你限制矢量图在200*200dp),越大的图片在屏幕上显示会消耗更长的时间进行绘制;

二、VectorDrawable
1.VectorDrawable简介

VectorDrawable定义了一个静态Drawable对象。和SVG格式非常相似,每个Vector图形被定义成一个树型结构,它由path和group对象组成。每条path包含对象轮廓的几何形状,每个group包含了变化的详细信息。所有path的绘制顺序和它们在XML出现的顺序相同;

2.VectorDrawable XML文件生成
Android Studio包含一个称为Vector Asset Studio的工具,它提供了一个简单的方法将矢量图以XML文件的形式添加到项目中。支持如下两种方式:
  添加Meterial Icon;
  导入可拉伸矢量图(SVG)和Adobe Photoshop文档(PSD)文件;
启动Vector Asset Studio
Android Studio->项目窗口->Android视图->选择res目录->New->Vector Asset(Android Plugin for Gradle 1.5.0或者更高);


使用Meterial Icon
Google meterial Design规范提供了meterial icons,你可以在你的Android app中使用。Vector Asset Studio帮助你选择,导入和设置meterial icon大小,定义透明度和Right-to-Left(RTL)镜像设置;

选择Meterial Icon->点击Icon按钮->Select Icon对话框(右边)->选择导入图片->OK,根据你的需要改变资源名称,大小,透明度和Right-To-Left镜像设置,点击Next按钮:

根据你的需要改变模块和资源目录,点击Finish按钮:

在app/src/main/res/drawable目录下,Vector Asset Studio添加了一个定义了适量图片的XML文件ic_assignment_ind_black_24dp.xml;

使用本地文件(SVG,PSD)
Vector Asset Studio也可以让你导入你自己的SVG和PSD文件。SVG是W3C一个基于XML的开源标准,PSD文件格式支持Adobe Photoshop。它支持基本的标准,但不支持所有的SVG和PSD功能。当你选择一个SVG或者PSD文件,它会立即给出是否支持图形编码的反馈。尽管矢量图支持一个或者更多的色彩,在许多场景下使用黑色图标(android:fillColor="#FF000000")。使用这种方式,你可以给你填充在布局中的矢量图添加一个tint,然后图标的颜色变成tint的颜色。如果图标的颜色不是黑色,图标的颜色可能和tint颜色混合;
选择Local file(SVG,PSD)->点击Path更多按钮->选择你要导入的图片->点击OK按钮->根据你的需要修改资源名称、大小、和透明度等属性->点击Next按钮(如果SVG或者PSD文件有一下不支持的功能,在Vector Asset Studio底部Errors会显示错误信息);

同上,根据你的需求改变资源输出的模块和目录->点击Finish按钮即可;

3.VectorDrawable使用
这里我们就简单使用一个Demo进行演示,显示两个图片和一个动画,目录如下:

构建兼容性配置
在Android 5.0之前(API level 21),Support Library 23.2或者更高的版本提供了矢量图片和矢量图片动画完整的支持。Android5.0之前的版本不支持矢量图,如果你支持最小API level是这些版本,你有如下两个选择:
  生成PNG文件;
  使用Support library;
为了在运行Android5.0(API level 21)之前版本设备不支持矢量图片和矢量图片动画,VectorDrawableCompat和AnimatedVectorDrawableCompat通过两个新的Support Libraries:support-vector-drawable和animated-vector-drawable分别进行支持;
在你app模块的build.gradle文件中添加vectorDrawables元素,使你的app使用矢量图support library;
flight/build.gradle文件

apply plugin: ‘com.android.library‘
android {
    ... ...
    defaultConfig {
        ... ...
        vectorDrawables.useSupportLibrary = true
    }
    ... ...
}
dependencies {
    ... ...
    compile ‘com.android.support:appcompat-v7:25.0.1‘
}

打包完成后,我们分析下APK打包了矢量图的xml文件;

我们也可以采用低版本构建生成PNG图片的兼容方式;
flight/build.gradle文件

apply plugin: ‘com.android.library‘
android {
    ... ...
    aaptOptions {
        additionalParameters "--no-version-vectors"
    }
    ... ...
}

打包完成后,我们分析下APK发现xml文件对应生成了对应png图片;

VectorDrawable定义
只需要一个资源文件(如上使用Vector Asset Studio导入)就可以创建矢量图片,而位图图片需要为每个屏幕密度提供一个文件。如果要创建一个矢量图片,在<vector>XML元素中定义如下:
flight/src/main/res/drawable/heart.xml文件

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportHeight="32"
    android:viewportWidth="32">
    <path
        android:fillColor="#8000"
        android:pathData="M20.5,9.5c-1.955,0,-3.83,1.268,-4.5,3c-0.67,-1.732,-2.547,-3,-4.5,-3C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5c5.207,-5.242,9,-7.97,9,-11.5C25,11.432,23.043,9.5,20.5,9.5z" />
</vector>

flight/src/main/res/drawable/battery.xml文件

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <group
        android:name="rotationGroup"
        android:pivotX="10.0"
        android:pivotY="10.0"
        android:rotation="15.0">
        <path
            android:name="vect"
            android:fillAlpha=".3"
            android:fillColor="#FF000000"
            android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z" />
        <path
            android:name="draw"
            android:fillColor="#FF000000"
            android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z" />
    </group>
</vector>

VectorDrawable引用
flight/src/main/res/layout/activity_flight.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto
    xmlns:tools="http://schemas.android.com/tools"
    ... ...
    tools:context="com.qunar.flight.FlightActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="flight" />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/heart"/>
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/battery"/>
</LinearLayout>

注意:如果你不使用support library兼容,使用生成png图片,那么不用添加命名空间,采用android:src属性即可;
运行结果

三、AnimatedVectorDrawable实践
1.AnimatedVectorDrawable简介

AnimatedVectorDrawable向矢量图添加动画属性。你可以分三个文件或者一个Drawable的XML文件定义矢量图动画。为了更好的理解,让我们来看看这两种方式:多个XML文件和单个XML文件;
2.多个XML文件
使用这种方式,你需要定义三个单独的XML文件:
  一个VectorDrawable XML文件;
  一个AnimatedVectorDrawable XML文件定义了目标VectorDrawable,动画用于目标path和group,属性和动画定义为ObjectAnimator对象或者AnimatorSet对象;
  一个动画XML文件;
AnimatedVectorDrawable多XML文件定义
首先我们想将哪个矢量图片动起来(vd.xml),该图片要运行什么样的动画(rotation.xml和path_morph.xml),将矢量图和动画结合(avd.xml);
flight/src/main/drawable/vd.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="vectorPath"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

flight/src/main/res/anim/rotation.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="6000"
        android:propertyName="rotation"
        android:valueFrom="0"
        android:valueTo="360" />
</set>

flight/src/main/res/anim/path_morph.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType"/>
</set>

flight/src/main/drawable/avd.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vd" >
    <target
        android:name="rotationGroup"
        android:animation="@anim/rotation" />
    <target
        android:name="vectorPath"
        android:animation="@anim/path_morph" />
</animated-vector>

AnimatedVectorDrawable引用
接下来,我们就可以在视图中应用该适量图片动画,运行动画;
flight/src/main/layout/activity_flight.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    ... ...
    tools:context="com.qunar.flight.FlightActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="flight" />
    ... ...
    <ImageView
        android:id="@+id/imageview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/avd"/>
</LinearLayout>

flight/src/main/java/com/qunar/flight/FlightActivity.java

public class FlightActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flight);

        ImageView imageView = (ImageView) findViewById(R.id.imageview1);
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof Animatable){
            ((Animatable) drawable).start();
        }
    }
}

运行效果

3.单个XML文件
使用这种方式,你可以合并相关的XML文件到一个使用XML Bundle格式的XML文件中。在构建app的时候,aapt tag会创建单独的资源并且在矢量动画引用它们。这种方式要求Build Tools 24或者更高,并且输出是向后兼容的;
AnimatedVectorDrawable单文件定义
flight/src/main/drawable/single_avd.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <aapt:attr name="android:drawable">
         <vector
             android:height="64dp"
             android:width="64dp"
             android:viewportHeight="600"
             android:viewportWidth="600" >
             <group
                 android:name="rotationGroup"
                 android:pivotX="300.0"
                 android:pivotY="300.0"
                 android:rotation="45.0" >
                 <path
                     android:name="v"
                     android:fillColor="#000000"
                     android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
             </group>
         </vector>
     </aapt:attr>
     <target android:name="rotationGroup"> *
         <aapt:attr name="android:animation">
             <objectAnimator
             android:duration="6000"
             android:propertyName="rotation"
             android:valueFrom="0"
             android:valueTo="360" />
         </aapt:attr>
     </target>
     <target android:name="v" >
         <aapt:attr name="android:animation">
             <set>
                 <objectAnimator
                     android:duration="3000"
                     android:propertyName="pathData"
                     android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
                     android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
                     android:valueType="pathType"/>
             </set>
         </aapt:attr>
      </target>
 </animated-vector>

注意:为了优化重绘性能,每个VectorDrawable对象创建了Bitmap缓存。因此,引用相同的VectorDrawable意味着共享相同的Btimap缓存。如果这些引用大小上不一致,Bitmap将会在大小每次变化的时候重建和重绘。换句话说,如果VectorDrawable使用了不同的大小,为每个大小创建VectorDrawable会效率更高;

四、代码库

QProject:https://github.com/Pengchengxiang/QProject  分支:ui/vectordrawable

时间: 2024-08-10 17:18:31

Android UI:矢量图使用的相关文章

在 Xcode 6 中使用矢量图( iPhone 6 置配 UI)

在 Xcode 6 中使用矢量图( iPhone 6 置配 UI) (本文转载:http://iosdeveloper.diandian.com/post/2014-09-25/40063062789) iOS应用程序是一个图像主导的产品.在开发一个应用程序时,你需要各种尺寸的图标,你需要为每个图像文件制作一个@1x 尺寸和一个@2x尺寸.这样你的应用看上去才足够精美.但缺点是你必须单独生成这些文件.随着iPhone6和iPhone6 Plus的到来,这个问题变得更加让人头疼:@3x 资源. 幸

android开发游记:VectorDrawable矢量图兼容性问题的解决方案

安卓5.0Lollipop发布以来VectorDrawable作为安卓环境下的矢量化图形的方式一直由于兼容性问题而很少被用到,由于只能用于5.0以上系统,导致现在多少安卓机无法使用而一直被开发人员无限搁置.在官方给出兼容性的解决方案之前,开发者社区已经有几个解决方案了.比如: https://github.com/trello/victor https://github.com/telly/MrVector https://github.com/wnafee/vector-compat 但是就效

Android使用SVG矢量图打造酷炫动效!

尊重原创,欢迎转载,转载请注明: FROM  GA_studio   http://blog.csdn.net/tianjian4592 一个真正酷炫的动效往往让人虎躯一震,话不多说,咱们先瞅瞅效果: 这个效果我们需要考虑以下几个问题: 1. 这是图片还是文字: 2. 如果是图片该如何拿到图形的边沿线坐标,如果是文字呢? 3. 如果拿到了边沿线坐标,如何让光线沿着路径跑动: 4. 怎么处理过程的衔接: 以上四个问题似乎不是太好处理,而这几个问题也正好是这个效果精华所在,接下来咱们一个一个进行考虑

Android 5.0+高级动画开发 矢量图动画 轨迹动画 路径变换

第1章 课程介绍为了成就更多高逼格的人才,我专门整理了Android5.0以后主推的实现酷炫动画的新技术,教你掌握实现动画的高逼格技巧.课程中我会详细讲解每个动画效果实现的原理和所用的技术,并带你一步一步的实现每个动画效果,让你在学完本次课程后,能够举一反三,再也不必担心设计MM的设计你没法实现了,也再也不用担心,老板的脑洞无... 第2章 矢量图VectorDrawable打造新时代酷炫动画本章讲解Android5.0以后主推的技术之一-矢量图VectorDrawable在Android中的使

Android 矢量图详解

官方文档 关于 Vector,在官方开发指南中介绍.本文章是由个人翻译官方指南然后添加个人理解完成. 由于个人精力有限,多个渠道发布,排版上可能会有问题,如果影响查看,请移步 Android 开发者家园 Vector Drawables 概述 VectorDrawable 和 AnimatedVectorDrawable 是在 Android 5.0 系统中第一次加入,当然我们可以使用 Android 的支持库,来支持旧的版本,通过 VectorDrawableCompat 和 AnimateV

在xcode6中使用矢量图(iPhone6置配UI)

ios应用程序是一个图像主导的产品.在开发一个应用程序时,你需要各种尺寸的图标,你需要为每个图像文件制作一个@1x尺寸和一个@2x尺寸.这样你的应用看上去才足够精美.但缺点是你必须单独生成这些文件.随着iphone6和iphone6 Plus的到来,这个问题变得更加让人头疼:@3x 资源. 幸运的是,苹果在xcode6中提供了一些伟大的工具来管理这些资源.更好的是,这种方式也让你的应用程序能够运行在未来的ios设备上打下了基础.工具之一是xcode6和ios8支持以Storyboard(或xib

Android UI相关开源项目库汇总

最近做了一个Android UI相关开源项目库汇总,里面集合了OpenDigg 上的优质的Android开源项目库,方便移动开发人员便捷的找到自己需要的项目工具等,感兴趣的可以到GitHub上给个star. 抽屉菜单 MaterialDrawer ★7337 - 安卓抽屉效果实现方案 Side-Menu.Android ★3865 - 创意边侧菜单 FlowingDrawer ★1744 - 向右滑动流动抽屉效果 SlidingRootNav ★1338 - 仿DrawerLayout的View

Android UI设计规范之2

界面尺寸 android的尺寸众多,建议使用分辨率为720×1280的尺寸设计.这个尺寸720×1280中显示完美,在1080×1920中看起来也比较清晰;切图后的图片文件大小也适中,应用的内存消耗也不会过高. 状态栏高度:50px 导航栏高度:96px 标签栏高度:96px Android最近出的手机都几乎去掉了实体键,把功能键移到了屏幕中,当然高度也是和标签栏一样的:96px 内容区域高度为:1038px (1280-50-96-96=1038) 1.安卓app设计规范之尺寸或分辨率 目前最

android UI设计时需要注意遵循的设计原则

1.Android设备屏幕尺寸分布 首先看一下各种屏幕的尺寸和屏幕密度划分,下图是各种屏幕尺寸对应的范围: 从上图可以看出,对应normal尺寸的屏幕范围集中在常见的3到5寸屏之间,large尺寸对应的就主要是5到7寸的nottpad之类的设备,例如三星的Note和Nexus7平板等,再网上走就是平板电脑了.接下来是屏幕密度(dpi),需要说明的时,平时所说的屏幕分辨率其实不能作为屏幕适配的依据,应该依据屏幕密度和屏幕尺寸来换算,屏幕密度是指每寸屏幕内容纳的像素数,屏幕密度从ldpi到xhdpi