2018正版葡京赌侠诗Android Vector曲折的匹配的路

Android Vector曲折的配合的路

个别年前写书之时段,就于研讨Android
L提出的Vector,可研究下发现,完全无具兼容性,相信就也是它没有吃大采用的一个缘由,经过Google的不懈努力,现在Vector终于迎来了其的青春。

4.jpg

于文章后,会被出本文的Demo和作用图,并开源在Github

Vector Drawable

Android 5.0颁布之时段,Google提供了Vector的支持。Vector
Drawable相对于一般的Drawable来说,有以下几只便宜:

  • Vector图像可以活动进行适配,不待经过分辨率来安装不同的图纸
  • Vector图像可以大幅回落图像的体积,同样一致摆设图,用Vector来贯彻,可能只有PNG的几十分之一
  • 运简易,很多企划工具,都足以直接导出SVG图像,从而转换成Vector图像
  • 功能强大,不用写过多代码就得实现非常复杂的卡通
  • 秋、稳定,前端已经老广泛的进行应用了

Vector图像刚揭晓之时段,是独支持Android 5.0+的,对于Android
pre-L的系统吧,并无克采用,所以,可以说那么时候的Vector并无什么卵用。不过自从AppCompat
23.2随后,Google对p-View的Android系统吧拓展了配合,也就是说,Vector可以行使于Android
2.1上述之有所系统,只需要引用com.android.support:appcompat-v7:23.2.0之上之版就得了,这时候,Vector应该算是迎来了她的春季。

安赢得Vector图像

概念

第一,需要讲解两个概念——SVG和Vector。

SVG,即Scalable Vector Graphics
矢量图,这种图像格式在前者被已用的充分普遍了,详见WIKI:https://en.wikipedia.org/wiki/Scalable\_Vector\_Graphics

Vector,在Android中指的凡Vector
Drawable,也便是Android中之矢量图,详见:https://developer.android.com/reference/android/graphics/drawable/VectorDrawable.html

因而,可以说Vector就是Android中之SVG实现,因为Android中之Vector并无是支撑周之SVG语法,也尚未必要,因为整体的SVG语法是非常复杂的,但都支持的SVG语法已经够了,特别是Path语法,几乎是Android中Vector的标配,详细可参见:http://www.w3.org/TR/SVG/paths.html

Vector语法简介

Android以相同种植简化的法子对SVG进行了相当,这种办法就是经应用它的Path标签,通过Path标签,几乎可兑现SVG中的别样具有标签,虽然可能会见复杂一点,但这些事物还是足以经过工具来就的,所以,不用操心写起来会要命复杂。

Path指令解析如下所示:

  1. 支撑之命令:

  2. M = moveto(M X,Y) :将画笔移动及指定的坐标位置

  3. L = lineto(L X,Y) :画直线到指定的坐标位置
  4. H = horizontal lineto(H X):画水平线至指定的X坐标位置
  5. V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
  6. C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三赖贝赛曲线
  7. S = smooth curveto(S X2,Y2,ENDX,ENDY)
  8. Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二不良贝赛曲线
  9. T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射
  10. A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线
  11. Z = closepath():关闭路径

  12. 采取标准:

  13. 为标轴为以(0,0)为核心,X轴水平往右侧,Y轴水平为下

  14. 拥有指令大小写均只是。大写绝对定位,参照全局坐标系;小写相对固化,参照父容器坐标系
  15. 指令和数据间的空格可以概括
  16. 一如既往指令出现反复得以只用一个

小心,’M’处理常,只是挪了画笔, 没有画任何东西。
它为堪于末端给出上同时绘制不总是线。

有关这些语法,开发者需要之并无是全部通,而是能看明白即可,其它的且足以付出工具来促成。

从PNG到SVG

  • 设计师

要是起一般用的PNG图像转换到SVG图像,对于设计师来说,并无是同码难事,因为多数底统筹工具(PS、Illustrator等等)都支持导出各种格式的图像,如PNG、JPG,当然,也席卷SVG,因此,设计师可以完全按照原来的艺术进行统筹,只是最后导出的时段,选择SVG即可。

  • 程序员

勿要求开发者都去读用这些计划工具,开发者可以行使一些家伙,自己转换一些较基础之图像,http://inloop.github.io/svg2android/
就是如此一个特别牛逼的网站,可以在线将日常图像转换为Android Vector
Drawable。如图所示:

5.png

抑或,还可以采用SVG的编辑器来进展SVG图像的编纂,例如http://editor.method.ac/

6.png

使用Android Studio

采用Android Studio的Vector
Asset,可以挺方便之创立Vector图像,甚至可以直接通过当地的SVG图像来生成Vector图像,如图所示:

2.png

跻身之后,就得生成Vector图像,如图所示:

3.png

Google的相当的路

只兼容L+

Vector是于Android L中取出来的新定义,所以当正开之上是只是兼容L+的。

Gradle Plugin 1.5的兼容

于Gradle Plugin 1.5始发,Google支持了同等种植兼容方式,即当Android
L之上,使用Vector,而以L之下,则利用Gradle将Vector生成PNG图像。

Android gradle plugin
1.5颁布后,加入了一个以及VectorDrawable有关的初效能。Android build
tools
提供了另外一栽缓解兼容性的方案,如果编译的版是5.0事先的版本,那么build
tools
会把VectorDrawable生成对应的png图片,这样以5.0之下的本子则利用的凡别的png图,而以5.0之上之版中虽然运用VectorDrawable.在build.gradle添加generatedDensities配置,可以配备生成的png图片的密度。

AppCompat23.2的兼容

起AppCompat23.2开始,Google开始支持以低版本及采取Vector。

静态Vector图像

咱俩发那么些主意会获得这些Vector,那么什么样使用它们啊,Android
5.0以上的用就不言了,不绝具广阔代表性,我们打pre-L版本的匹配开始举行打。

pre-L版本兼容

VectorDrawableCompat依赖于AAPT的有效能,它能维系最近矢量图使用的丰富之性能ID,以便他们可叫pre-L版本之前的援。

当Android
5.0前用Vector,需要aapt来对资源进行一些甩卖,这无异过程得在aapt的部署中展开设置,如果没启用这样一个flag,那么在5.0之下的配备及运行就会生出android.content.res.Resources$NotFoundException。

率先,你待以路的build.gradle脚本中,增加对Vector兼容性的支撑,代码如下所示:

使用Gradle Plugin 2.0以上:

android {

    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

使用Gradle Plugin 2.0以下,Gradle Plugin 1.5以上:

android {
  defaultConfig {
    // Stops the Gradle plugin’s automatic rasterization of vectors
    generatedDensities = []
  }
  // Flag to tell aapt to keep the attribute ids around
  aaptOptions {
    additionalParameters "--no-version-vectors"
  }
}

譬如前提到的,这种兼容方式实在是先行关闭AAPT对pre-L版本采用Vector的服,即在L版本上述,使用Vector,而于pre-L版本及,使用Gradle生成相应的PNG图片,generatedDensities这个数组,实际上就是若生成PNG的图分辨率的数组,使用appcompat后即便非需这样了。

自,最重大之抑添加appcompat的支撑:

compile 'com.android.support:appcompat-v7:23.4.0'

再就是,确保您利用的是AppCompatActivity而不是平常的Activity。

Vector图像

一个中心的Vector图像,实际上为是一个xml文件,如下所示:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="200dp"
        android:height="200dp"
        android:viewportHeight="500"
        android:viewportWidth="500">

    <path
        android:name="square"
        android:fillColor="#000000"
        android:pathData="M100,100 L400,100 L400,400 L100,400 z"/>

</vector>

亮如图所示:

7.png

此需要解释下此的几乎个标签:

  • android:width \ android:height:定义图片的宽高
  • android:viewportHeight \
    android:viewportWidth:定义图像为剪切的百分比大小,例如例子中的500,即把200dp大小的图像划分成500份,后面Path标签中的坐标,就整个以的是这里划分后底坐标体系。

这么做生一个不胜好的意,就是将图像大小以及图像分离,后面可以无限制修改图像大小,而不需修改PathData中之坐标。

  • android:fillColor:PathData中之这些性就不详细讲了,与Canvas绘图的习性基本相仿。

每当控件被使用

来矣静态的Vector图像,就足以以控件被利用了。

足发现,这里我们应用的都是平凡的ImageView,好像并无是AppcomatImageView,这是以运用了Appcomat后,系统会活动把ImageView转换为AppcomatImageView。

ImageView\ImageButton

对于ImageView这样的控件,要配合Vector图像,只待用前的android:src属性,换成app:srcCompat即可,示例代码如下所示:

<ImageView
    android:id="@+id/iv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/vector_image"/>

以代码中安装的话,代码如下所示:

ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageResource(R.drawable.vector_image);

setBackgroundResource也是可以装Vector的API

Button

Button并无可知直接动用app:srcCompat来利用Vector图像,需要通过Selector来拓展下,首先,创建两独图像,用于Selector的一定量个状态,代码如下所示:

selector1.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="M14.59,8L12,10.59 9.41,8 8,9.41 10.59,12 8,14.59 9.41,16 12,13.41 14.59,16 16,14.59 13.41,12 16,9.41 14.59,8zM12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</vector>

selector2.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,15h2v2h-2zM11,7h2v6h-2zM11.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,8z"/>
</vector>

selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/selector1" android:state_pressed="true"/>
    <item android:drawable="@drawable/selector2"/>
</selector>

非常简单,只是将一般的Selector中的图像换成了Vector图像而已,接下,在Button中行使这个Selector即可:

<Button
    android:id="@+id/btn"
    android:layout_width="70dp"
    android:layout_height="70dp"
    android:background="@drawable/selector"/>

然后运行,如果你认为可以运行,那便是极其天真了,都说了凡相当,怎么能够没坑呢,这里就是是一个坑……

此坑实际上是发出历史渊源的,Google的同样员开发者在博客中描绘及:

First up, this functionality was originally released in 23.2.0, but
then we found some memory usage and Configuration updating issues so
we it removed in 23.3.0. In 23.4.0 (technically a fix release) we’ve
re-added the same functionality but behind a flag which you need to
manually enable.

实际,他们的是改变,就影响了看似DrawableContainers(DrawableContainers
which reference other drawables resources which contain only a vector
resource)这样的好像,它的一个杰出,就是Selector(StateListDrawable也是)。这个开发者在文中涉及的flag,就是下边的就段代码,放在Activity的先头就是好了:

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

拉开这个flag后,你就算足以健康下Selector这样的DrawableContainers了。同时,你还被了接近android:drawableLeft这样的compound
drawable的采用权限,以及RadioButton的施用权力,以及ImageView’s src属性。

RadioButton

RadioButton的Button同样可定义,代码如下所示:

<RadioButton
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:button="@drawable/selector"/>

动态Vector基础

动态Vector才是Android Vector Drawable的花所在

动态的Vector需要通过animated-vector标签来进展落实,它就像一个粘合剂,将控件与Vector图像粘合在了共同,一个基础之animated-vector代码如下所示:

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/XXXXX1">

    <target
        android:name="left"
        android:animation="@animator/XXXXX2"/>

</animated-vector>

实在就其间只生三三两两个主要是得关注的,XXXXX1和XXXXX2。一个有血有肉的以身作则如下所示:

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_arrow">

    <target
        android:name="left"
        android:animation="@animator/anim_left"/>

    <target
        android:name="right"
        android:animation="@animator/anim_right"/>

</animated-vector>

此表示目标图像是drawable/ic_arrow,对left、right分别采用了anim_left、anim_right动画。这里的name属性,就是于静态Vector图像中group或者path标签的name属性。

animated-vector标签在现在的Android
Studio中其实是会报错的,但这并无影响编译和运作,属于Android
Studio的Bug。

对象图像

XXXXX1凡目标Vector图像,也就算是静态的Vector图像,例如:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="120dp"
        android:height="120dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">

    <group android:name="left">
        <path
            android:fillColor="#FF000000"
            android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3"/>
    </group>

    <group android:name="right">
        <path
            android:fillColor="#FF000000"
            android:pathData="M14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4"/>
    </group>

</vector>

得窥见,这里的Vector图像比前我们看见的使多了一个group标签。group标签的打算产生有限独:

  • 本着Path进行分组,由于我们后要针对Path进行动画,所以可以让拥有同样动画效果的Path在与一个Group中
  • 进展动画效果,单个的path标签是从来不translateX和translateY属性的,因此无法利用性能动画来决定path
    translateY,而group标签是部分,所以我们需要事先用有关的path标签元素包裹在一个个之group标签中.

卡通效果

XXXXX2实际上即便是模板要促成之卡通,动画效果实在就是是基础的特性动画,例如:

anim_left.xml

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:interpolator/anticipate_overshoot"
    android:propertyName="translateX"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:valueFrom="0"
    android:valueTo="-10"
    android:valueType="floatType"/>

anim_right.xml

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:interpolator/anticipate_overshoot"
    android:propertyName="translateX"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:valueFrom="0"
    android:valueTo="10"
    android:valueType="floatType"/>

当代码中以

ImageView imageView = (ImageView) findViewById(R.id.iv);
AnimatedVectorDrawableCompat animatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create(
        this, R.drawable.square_anim
);
imageView.setImageDrawable(animatedVectorDrawableCompat);
((Animatable) imageView.getDrawable()).start();

动态Vector兼容性问题

向下兼容问题

相同说及相当,就只能干坑,几乎所有的为配合而召开的转移,都见面养有不行填满的坑,动态Vector动画也未例外,虽然Google已经针对Vector图像进行了Android
2.1以上之配合,但对动态Vector动画,还是时有发生那么些限的,例如:

  • Path Morphing,即路径变换动画,在Android pre-L版本下是力不从心运用的。
  • Path Interpolation,即路径插值器,在Android
    pre-L版本只能采取系统的插值器,不可知由定义。
  • Path
    Animation,即路径动画,这个貌似用贝塞尔曲线来取代,所以无最好可怜影响。

前进兼容问题

而外在亚版本及之兼容性问题,在L版本之上,也存兼容性问题,即承了AppCompatActivity的界面,如果直白装ImageView的srcCompat,那么Path
Morphing动画是无力回天生效之,因为默认的AppCompatActivity已经默认使用ImageViewCompat给换了,但是AnimatedVectorDrawableCompat是勿支持Path
Morphing动画的,所以,在AppCompatActivity界面里面纵使没用了。

解决办法很简单,即利用代码来被ImageView添加动画:

ImageView imageView = (ImageView) view;
AnimatedVectorDrawable morphing = (AnimatedVectorDrawable) getDrawable(morphing);
imageView.setImageDrawable(morphing);
if (morphing != null) {
    morphing.start();
}

留意不要采用AnimatedVectorDrawableCompat即可。

抽取string兼容问题

开发者有时候为代码简洁可能会见把Vector图像中的pathData放到string.xml中,然后以Vector图像中援string。

而这种艺术而由此生成png来配合5.0之下机型的话,会报pathData错误,编译器不见面去读取string.xml,只能拿pathData写及Vector图像中,动画文件中吗是如出一辙,这吗是为着配合做出的自我牺牲呢,不得而知。

另兼容问题

其他非常意外、诡异、不克领略的兼容性问题,只能通过本文件夹的法门来进展兼容了,例如drawable-v21和drawable,分别创建两独文本称相同之资源以个别个公文夹下,这样在21以上版本,会以drawable-v21之资源,而别会使drawable下的资源。

动态Vector进阶

用好ObjectAnimator

所谓Vector动画进阶,实际上就是于运ObjectAnimator的片段性质,特别是trimPathStart、trimPathEnd这半个对Vector的习性(要留意pathData属性不般配pre-L)。

随即简单只属性之法定文档如下所示:

android:trimPathStart
The fraction of the path to trim from the start, in the range from 0 to 1.
android:trimPathEnd
The fraction of the path to trim from the end, in the range from 0 to 1.
android:trimPathOffset
Shift trim region (allows showed region to include the start and end), in the range from 0 to 1.

实际上挺简单,就是一个图像的截取,设置一个比例即可,即眼前绘制多少比例之图像,其余部分不绘制,Start和End分别就是于PathData的Start和End开始算,大家参考几只例证就是会了解了。

理解Path Morph

Path
Morph动画是Vector动画的一个高档应用,说到底,也就是简单个PathData的转移,但是这种转移并无是依心所欲的,对于片只PathData,它们会展开Path
Morph的前提是,它们拥有相同个数的严重性点,即有限单途径的换,只是关键点的坐标变化,掌握了马上一个基本原理,实现Path
Morph就非常容易了。

学习Vector

在Github上自己开始源了一个Vector的卡通Demo库,地址如下所示:

https://github.com/xuyisheng/VectorDemo

夫Demo分为简单有,一部分是可以兼容Android
pre-L版本和L+版本的Vector动画,另一样片(通过Actionbar的按钮切换)是只能兼容L+的Vector动画。

每个Vector动画,基本还包含四部分内容,即:

  • Vector:图像资源
  • Animated-vector:动画、图像粘合剂
  • ObjectAnimator:动画资源
  • 代码:启动动画

每个Vector动画通过就四只有去开展辨析,就好清楚了。

此展示下Demo的力量图:

vector.gif

Vector性能问题

发生读者以篇章尾留言,询问VectorDrawable的特性问题,这里解释一下。

  1. Bitmap的绘图效率并不一定会比较Vector高,它们发出必然的平衡点,当Vector比较简单时,其效率是自然比Bitmap高的,所以,为了保险Vector的高效率,Vector需要更简约,PathData更加规范、精简,当Vector图像变得非常复杂时,就得运用Bitmap来代替了
  2. Vector适用于ICON、Button、ImageView的图标等小之ICON,或者是急需的动画片效果,由于Bitmap在GPU中出缓存功能,而Vector并没,所以Vector图像不能够开往往之重绘
  3. Vector图像过于复杂时,不仅仅要留心绘制效率,初始化效率呢是待考虑的主要因素
  4. SVG加载速度会急忙被PNG,但渲染速度会缓慢于PNG,毕竟PNG有硬件加速,但平均下来,加载速度之提升弥补了绘图的速度缺陷。
    Google的之视频中,已经针对性Vector的频率问题开了讲,可以参照下:

参考

https://medium.com/@shemag8/animated-vector-drawable-e4d7743d372c\#.3vkt12j20
https://github.com/jpuderer/AnimatedButton

发表评论

电子邮件地址不会被公开。 必填项已用*标注