VectorDrawable 和 AnimatedVectorDrawable 的兼容性问题

作者: rain 分类: 移动 发布时间: 2016-01-09 00:49 6 条评论

前面分别介绍了 VectorDrawableAnimatedVectorDrawable 。 本文来介绍下 Android 开发工具对矢量图兼容性的支持。

VectorDrawable 兼容性的支持方式

在 Android 官方还没有给出兼容性解决方案的时候, 开发者社区已经有几个解决方案了。比如:
https://github.com/trello/victor
https://github.com/telly/MrVector
https://github.com/wnafee/vector-compat
其中 vector-compat 算是比较好的一个解决方式,在 5.0 系统上直接使用系统的实现。在旧版本上使用兼容的实现。而传言 Android 团队也准备推出官方的 support 包,比如 可以在 Android 代码库中看到相关的代码:
VectorDrawableCompat.java AnimatedVectorDrawableCompat.java
但是 一年半过去了, Android 官方的 Support 包还是不见踪影,个人猜测应该是性能的问题导致官方一直没有像 vector-compat 一样直接提供一个 Support 来支持 SVG。

但是在并不意味着官方就不考虑 VectorDrawable 的兼容性问题了。在 Android gradle plugin 1.4 beta2发布的时候,让人终于看到了希望:

VectorDrawable to png

Android gradle plugin 1.4 beta2的 发布版本说明中有如下说明:
Vector drawable support for generating PNGs at build time.
* PNGs are generated for every vector drawable found in a resource directory that does not specify an API version (or specifies a version lower than 21).
* This only happens if minSdk is below 21.
* Densities to use can be set using the new “generatedDensities” property in defaultConfig or per-flavor.

看来 VectorDrawableCompat 包是不会有了, Android build tools 提供了另外一种解决兼容性的方案,在编译的时候把 VectorDrawable 生成对应的 png 图片,这样在 5.0之前的版本上直接使用 png图片而不是使用矢量图。 还可以通过 generatedDensities 来配置需要生成的 Densities。

比如:

然后 Build 项目,查看生成的pngs图位于如下目录:
…\app\build\generated\res\pngs

如果没有配置 generatedDensities 则会生成所有 屏幕密度 对应的 png 图片。
如果指定了 generatedDensities 则只生成 指定的图片。

注意,这里有个 drawable-anydpi-v21 目录, anydpi 是啥玩意啊?和 nodpi 一样,Android 对这玩意也没有对应的文档,还好有人研究了一下,结果看这里

简单来说, anydpi 就是任意 dpi 都适用,比如上面的 drawable-anydpi-v21 ,如果你的手机版本是 21+(Android 5.0 以及以上系统),则不管你的手机屏幕密度的多少,都会用 drawable-anydpi-v21 里面的资源(如果有的话)。而 nodpi 就是如果其他地方(xhdpi、mdpi、hdpi 等)都找不到对应的资源了,就用这个里面的。所以 VectorDrawable 是放到 drawable-anydpi-v21 中的。而其他生成的 png 图放到对应的 屏幕密度目录里面去。

通过生产png 图的方式,确实没有性能问题了, 在编译的时候都把兼容性给你解决好了。但是 这种方式生成的是静态图片,无法支持 AnimatedVectorDrawable 。 所以 对于 AnimatedVectorDrawable 在 Android 5.0 之前的版本是无法使用了,如果你想使用该功能,则请考虑 使用 https://github.com/wnafee/vector-compat

由于 AnimatedVectorDrawable 并不支持 5.0 之前的版本,所以在使用 SVG 资源的时候需要注意了。
如果您不考虑支持 5.0之前的版本,则没有需要特别注意的地方。如果你考虑支持 5.0之前的版本,则请把 VectorDrawable 资源放到 drawable 目录中;把 AnimatedVectorDrawable 放到 drawable-v21 目录中,并且在 drawable 中提供一个和 AnimatedVectorDrawable 同名字的 资源来在 5.0之前的版本使用。

比如 在 Plaid res/drawable/avd_heart_empty.xml 项目中有个喜欢的动画。 由于 AnimatedVectorDrawable 无法在 5.0之前系统使用。所以需要把 avd_heart_empty.xml 放到 res/drawable-v21/avd_heart_empty.xml 目录,并在 res/drawable/avd_heart_empty.xml 供 5.0之前的系统使用。在这个 xml 文件中可以使用一个 selector 来替代这个动画:




另外还需要注意的是,为了保持 VectorDrawable xml 文件的简介性, 你可以把 pathData 数据放到一个单独的 xml 文件中作为一个 string item。然后通过 @string/ 来应用。例如 android:pathData=”@string/path_comment”。 如果你打算通过 生成 png 图片的方式支持 5.0之前的版本,则你无法这样使用。 Gradle plugin 在编译的时候,不会去解析 string xml文件。直接报错说 pathData错误。

最后:需要注意的是,如果你从其他地方下载一个 svg图片,例如 这个图片:
https://www.iconfinder.com/icons/367617/download/svg/128

通过 Android Studio 或者 通过 http://inloop.github.io/svg2android/ 工具转换为 VectorDrawable xml文件的时候, 他们都是直接把 android:viewportXXX 画布尺寸作为 android:width 和 android:height 的,并且用 dp 为单位,比如 https://www.iconfinder.com/icons/367617/download/svg/128 转换的结果为:

由于画布 android:viewport 的尺寸为 512 x 512,所以工具自动把 android:width=”512dp” 和 android:height=”512dp” 也设置为 512dp, 如果你只是想要一个 48dp 的机器人小图标,则请记得把 android:width=”512dp” 和 android:height=”512dp” 修改为 android:width=”48dp” 和 android:height=”48dp” ;这样最终生成的 png 图片就是 48dp 大小的而不是 512dp 大小的大图片。避免生成很多大图片导致性能问题。

本文出自 云在千峰,转载时请注明出处及相应链接。

本文永久链接: http://blog.chengyunfeng.com/?p=836

Ɣ回顶部