热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[译]在Android中使用VectorDrawable

原文链接:VectorsForAll(almost)原文作者:stylingandroid译者:edvardhua校对者:SatanWoo,zhangzhaoqi经常阅读Styli
  • 原文链接 : Vectors For All (almost)
  • 原文作者 : stylingandroid
  • 译者 : edvardhua
  • 校对者: SatanWoo, zhangzhaoqi

经常阅读 Styling Android 的读者会知道我有多么喜欢用 VectorDrawableAnimatedVectorDrawable 。直到我在写这篇文章之前我还在等待 VectorDrawableCompat (译者注:之前大家以为官方会出兼容 Support ,后来官方使用了另外一种方案,详细内容可戳该链接),所以目前矢量图只能够在 API 21+ (Lollipop) 上面使用。然而,Android Studio 1.4 增加了对旧 android 的兼容,所以,实际上可以在低于 Lollipop 版本的机器上面使用 VectorDrawable

在使用之前先来快速回顾一下什么是 VectorDrawable 。 本质上来说它其实就是安卓对 SVG path data 的一层封装。而 SVG paths 是一种以 xml 方式描述复杂图形元素的东西。(译者注:感兴趣的可以阅读 W3C 的官方文档) SVG 很适合用来储存线条和矢量图像,但不适合用来储存摄影图像。通常在Android中 ShapeDrawable 可以实现一些线条和形状的绘画。 但大多数情况我们会将这些矢量图转换成不同像素密度位图来使用。在这篇文章中,我们将会一起来探索如何使用它。

Android Studio 1.4 介绍了如何将SVG图像导入到 Android Studio 然后再自动转换为 VectorDrawable 。这些图标可以来自 material icons pack 或者是单独的 SVG 文件。导入 material icons 的确可以和 VectorDrawable 配合的天衣无缝,同时 google 也提供了大量的 icon 供我们选择。然而,导入单独的 SVG 文件会产生诸多的问题。产生这些问题的主要原因是 VectorDrawable 只支持一部分的 SVG 特性,而像图像渐变,填充和本地 IRI 引用(能够给元素一个唯一的索引,然后在 SVG 内通过索引重用)以及图像的变换等一些我们经常使用的特性都不支持。

举个例子,即使是如官网 LOGO 这样简单的一个SVG图像(如下图所示)都不能导入到 Android 中,因为他使用了本地的IRI引用。

《[译] 在 Android 中使用 VectorDrawable》

现在还不太清楚 Android 去除这些特性是否是出于性能方面原因,(譬如,渐变效果的渲染会比较复杂一点)或者说是为了以后开发的考虑。

如果你足夠了解 SVG 的格式(这个已经不属于本文的讨论范畴了)我们可以手动的修改图标,然后移除本地 IRI 引用,我们可以对刚才提到的图标可以使用这个方法。

《[译] 在 Android 中使用 VectorDrawable》

然而仍然不能够导入到 Android ,因为会抛出 “premature end of file” 的错误信息,并且会指出出现问题的那行。感谢来自Wojtek Kaliciński 的建议,我将 SVG 中 width 和 height 的值从百分比改成绝对值之后就可以导入到 Android 中去了。但是因为水平和竖直移动(Translations)特性不支持,导致所有的元素摆放位置不好。

《[译] 在 Android 中使用 VectorDrawable》

通过手动将所有的平移(translation)和旋转(rotation)变换从原来的 SVG 格式转换到 Android 中所支持的格式后(在包含来支持变换),我终于能够将 SVG 图标导入,并使用 VectorDrawable 将其在 Marshmallow 上正确渲染。

《[译] 在 Android 中使用 VectorDrawable》

使用 Juraj Novák 所开发的 svg2android 工具可以方便的将 SVG 转换成 VectorDrawable 。该工具也有限制,那就是不能处理渐变和本地 IRI 引用的问题。但是可以省去我们手动微调的工作还是很不错的,像我刚才提到的宽高的问题,使用该工具转换则没有抛出错误。该工具开启实验性模式后还支持图像的变换(Transformation)并且支持的很好。但是对于本地的IRI引用还是需要我们手动的去修改原生的 SVG 文件。

将转换后的文件放到 res/drawable 文件夹后,我们可以直接当成 drawable 来引用,如下代码所示:


xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
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=".MainActivity">
android:layout_
android:layout_
android:cOntentDescription="@null"
android:src="@drawable/svg_logo2" />

假如我们使用的 gradle plugin 版本是 1.4.0 或者更高的话(截至到我写这篇文章之前,还未正式发布1.4.0,但是 1.4.0-beta6 已经可以实现这个效果了),那么他将适配到 Android API 1。

那么,适配低版本的原因是什么呢?让我们来看一下Build文件夹里面所生成的代码,答案就已经很明显了。

《[译] 在 Android 中使用 VectorDrawable》 Screen Shot 2015-10-03 at 15.20.33

针对于 API 21 或者更高版本的设备,我们导入的矢量 XML drawable 文件将会被使用,但是对于早起的版本,我们则使用 PNG 代替矢量的 drawable 。

但是如果我们出于 apk 大小的考虑,并不想生成多个 PNG 文件来适配多个分辨率呢?我们可以通过设置 generatedDensities 的值来决定需要生成 PNG 的分辨率和数量。

apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.stylingandroid.vectors4all"
minSdkVersion 7
targetSdkVersion 23
versionCode 1
versionName "1.0"
generatedDensities = ['mdpi', 'hdpi']
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
}

如果我们现在进行 build ,我们会发现它(记住,在 build 之前先清除上一次 build 生成的 PNG 文件)只生成了我们指定的分辨率大小的 PNG 文件。

《[译] 在 Android 中使用 VectorDrawable》 Screen Shot 2015-10-03 at 15.27.08

所以,现在来看一下这些 PNG 图片里面的内容是什么:

《[译] 在 Android 中使用 VectorDrawable》

这些图片本质上跟我之前未修改的 SVG 图像的内容是相同的。我需要提醒大家,这里会抛出警告信息,告诉我们 元素不支持生成栅格化的图片格式。但是这并不能消除 VectorDrawable 是 Android 中特有的格式,而且该格式不支持上述特性,这让我们感到很困惑的事实。

我们现在开始了解为什么图像的变换特性在导入工具中不被支持了,因为 VectorDrawable 中的 元素不支持导出栅格化的图片格式,从而导致不能够向前兼容的问题。这个看上去是一个重大的疏忽:因为在 Lollipop 上面渲染正常的 VectorDrawable 资源,在将他们转换成 PNG 后则不能够正确的渲染。

总结:如果使用这些新的工具从 material icons 库导入资源,那么它们则能够完美无瑕的渲染。但是,我们需要注意的是它们只具备导入 SVG 的能力以及只支持 SVG 一部分特性的转换,所以这导致了它们不能够导入现实世界中大部分的 SVG 文件。此外,对于新工具中将 VectorDrawable 转换成 PNG 来适配低版本的机器的时候是不支持像素图转换的,这让我们觉得新工具的功能还没有完成还不能够拿来使用。

其实这种层次的手动微调花不了太多的时间(譬如修改官方 logo ),尤其我们是先用转换工具将它们转换成 VectorDrawable 后。尽管我仍然需要手动的修改图像变换所涉及到的全部坐标,也就是 SVG pathData 的元素内容。

让我们期望这些问题在新的工具上会得到解决。这样这些有潜力的新工具才能够开始达到它们原来的目标。

这篇文章的源代码可以在这里找到。


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 今天就跟大家聊聊有关怎么在Android应用中实现一个换肤功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
    android触屏处理流程,android触摸事件处理流程?FOOKWOOD「建议收藏」最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到A ... [详细]
author-avatar
jimmy2702933123
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有