VectorDrawable-第一章

編輯推薦:稀土掘金,這是一個針對技術開發者的一個應用,你可以在掘金上獲取最新最優質的技術乾貨,不僅僅是Android知識、前端、後端以至於產品和設計都有涉獵,想成爲全棧工程師的朋友不要錯過!

VectorDrawable:適應不同分辨率的drawable資源 一文中我們介紹了VectorDrawable,只是簡單的作爲一個引子,文中也提到了會翻譯幾篇關於VectorDrawable的文章,本文就是stylingandroid網站的幾篇文章譯文的第一篇:

以下爲譯文:


Lollipop中有一個非常好的新特性是VectorDrawable以及相關的一些類,他們爲我們提供了添加複雜矢量圖形的強大功能,同時也提供了動畫顯示這些圖形的方法。矢量圖形的好處是放大不會失真,可以適應不同分辨率的屏幕。這個文章系列我們將瞭解這些類以及它們的優點,以及如何用相對較少的代碼實現吸引人的效果。

 

 簡單的來說,矢量圖形就是使用幾個形狀的方式來描述一個圖像元素。矢量圖形非常適合於與設備無關的簡單或者合成的製圖或者不需要實現真實感的場合。Adobe Illustrator和Inkscape 常用來製作矢量圖形。而位圖(Bitmap ),則完全相反,位圖是定義每一個像素點的顏色來顯示一張圖片,它適合顯示一張真實的照片。矢量圖形的一大好處是它的渲染是在運行時開始的,因此它可以自適應不同的屏幕。由於矢量圖其實保存的只是描述幾何圖形的文本,因此它只佔用非常少的空間。當然因爲需要在運行時將這些字符串轉換成圖像,花費多一點點的cpu是肯定的。

 

矢量圖形在安卓的Lollipop中已經實現了,相關的類就是VectorDrawable 。(雖然第三方的MrVector 已經實現了VectorDrawable 兼容Lollipop 之前的設備,但是它並沒有實現後面會講到的AnimatedVectorDrawable )。VectorDrawable 的出現意味着以前我們放在mdpi, hdpi, xhdpi, xxhdpi中的部分圖片資源(適合用矢量圖描述的,比如圖標)只用一個VectorDrawable 替代就可以了。

爲了說明,我找了下面這張svg文件(這個文件可以從library for displaying SVG graphics in Android 中獲取到),圖片是一個機器人 :

android


這個文件的svg格式只有2265字節,但是如果我們將它轉換成500 x 500的bitmap文件,保存成png格式,則有13272 字節。並且它可以自動伸縮爲任意大小的圖片,而位圖就需要使用多張才能達到不同分辨率的效果。不過,這裏以svg作爲例子還是有點問題,因爲svg並非VectorDrawable,所以我們不能直接使用svg圖片。但是VectorDrawable 支持svg的一部分規則,我們可以將svg中的某些數據用在VectorDrawable中。主要其實就是svg中定義path的那部分數據。Svg的path類似於android.graphics.Path api,只不過是用字符串定義的,我們看看svg的源碼就知道了:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
  3. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  4. <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
  5.      width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
  6. <g id="max_width__x2F__height" display="none">
  7.     <path display="inline" d="M499.001,1v498H1V1H499.001 M500.001,0H0v500h500.001V0L500.001,0z"/>
  8. </g>
  9. <g id="androd">
  10.     <path fill="#9FBF3B" d="M301.314,83.298l20.159-29.272c1.197-1.74,0.899-4.024-0.666-5.104c-1.563-1.074-3.805-0.543-4.993,1.199
  11.         L294.863,80.53c-13.807-5.439-29.139-8.47-45.299-8.47c-16.16,0-31.496,3.028-45.302,8.47l-20.948-30.41
  12.         c-1.201-1.74-3.439-2.273-5.003-1.199c-1.564,1.077-1.861,3.362-0.664,5.104l20.166,29.272
  13.         c-32.063,14.916-54.548,43.26-57.413,76.34h218.316C355.861,126.557,333.375,98.214,301.314,83.298"/>
  14.     <path fill="#FFFFFF" d="M203.956,129.438c-6.673,0-12.08-5.407-12.08-12.079c0-6.671,5.404-12.08,12.08-12.08
  15.         c6.668,0,12.073,5.407,12.073,12.08C216.03,124.03,210.624,129.438,203.956,129.438"/>
  16.     <path fill="#FFFFFF" d="M295.161,129.438c-6.668,0-12.074-5.407-12.074-12.079c0-6.673,5.406-12.08,12.074-12.08
  17.         c6.675,0,12.079,5.409,12.079,12.08C307.24,124.03,301.834,129.438,295.161,129.438"/>
  18.     <path fill="#9FBF3B" d="M126.383,297.598c0,13.45-10.904,24.354-24.355,24.354l0,0c-13.45,0-24.354-10.904-24.354-24.354V199.09
  19.         c0-13.45,10.904-24.354,24.354-24.354l0,0c13.451,0,24.355,10.904,24.355,24.354V297.598z"/>
  20.     <path fill="#9FBF3B" d="M140.396,175.489v177.915c0,10.566,8.566,19.133,19.135,19.133h22.633v54.744
  21.         c0,13.451,10.903,24.354,24.354,24.354c13.451,0,24.355-10.903,24.355-24.354v-54.744h37.371v54.744
  22.         c0,13.451,10.902,24.354,24.354,24.354s24.354-10.903,24.354-24.354v-54.744h22.633c10.569,0,19.137-8.562,19.137-19.133V175.489
  23.         H140.396z"/>
  24.     <path fill="#9FBF3B" d="M372.734,297.598c0,13.45,10.903,24.354,24.354,24.354l0,0c13.45,0,24.354-10.904,24.354-24.354V199.09
  25.         c0-13.45-10.904-24.354-24.354-24.354l0,0c-13.451,0-24.354,10.904-24.354,24.354V297.598z"/>
  26. </g>
  27. </svg>

看起來很亂,我們不需要知道其內部的細節,只把我們用得着的東西篩選出來就行了。<svg> 標籤中定義了一些屬性:畫布以及視圖區域大小爲500 x 500 px,然後有一個<g>標籤,裏面定義了一個描邊,忽略掉就是了。再後又是一個<g>標籤,這個標籤的id爲“android”,這部分裏面的東西纔是機器人logo自身的數據,也是我們需要的數據。它包含了6個<path> 元素,分別定義head、左眼、右眼、左手、身體和腳、右手。每一個path中的fill 屬性定義填充色(可以看到,除了眼睛爲白色之外,所有的填充色都是綠色),fill屬性之後是包含path數據的屬性d。想了解d屬性中數據定義的可以參考SVG Path Specification ,但是這個不重要,因爲我們只需簡單的把這裏面的數據直接用在VectorDrawable中就可以了。

 

好了,我們來創建一個VectorDrawable:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <vector xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:viewportWidth="500"
  4.     android:viewportHeight="500"
  5.     android:width="500px"
  6.     android:height="500px">
  7.     <group android:name="android">
  8.         <path
  9.             android:name="head"
  10.             android:fillColor="#9FBF3B"
  11.             android:pathData="M301.314,83.298l20.159-29.272c1.197-1.74,0.899-4.024-0.666-5.104c-1.563-1.074-3.805-0.543-4.993,1.199L294.863,80.53c-13.807-5.439-29.139-8.47-45.299-8.47c-16.16,0-31.496,3.028-45.302,8.47l-20.948-30.41c-1.201-1.74-3.439-2.273-5.003-1.199c-1.564,1.077-1.861,3.362-0.664,5.104l20.166,29.272c-32.063,14.916-54.548,43.26-57.413,76.34h218.316C355.861,126.557,333.375,98.214,301.314,83.298" />
  12.         <path
  13.             android:name="left_eye"
  14.             android:fillColor="#FFFFFF"
  15.             android:pathData="M203.956,129.438c-6.673,0-12.08-5.407-12.08-12.079c0-6.671,5.404-12.08,12.08-12.08c6.668,0,12.073,5.407,12.073,12.08C216.03,124.03,210.624,129.438,203.956,129.438" />
  16.         <path
  17.             android:name="right_eye"
  18.             android:fillColor="#FFFFFF"
  19.             android:pathData="M295.161,129.438c-6.668,0-12.074-5.407-12.074-12.079c0-6.673,5.406-12.08,12.074-12.08c6.675,0,12.079,5.409,12.079,12.08C307.24,124.03,301.834,129.438,295.161,129.438" />
  20.         <path
  21.             android:name="left_arm"
  22.             android:fillColor="#9FBF3B"
  23.             android:pathData="M126.383,297.598c0,13.45-10.904,24.354-24.355,24.354l0,0c-13.45,0-24.354-10.904-24.354-24.354V199.09c0-13.45,10.904-24.354,24.354-24.354l0,0c13.451,0,24.355,10.904,24.355,24.354V297.598z" />
  24.         <path
  25.             android:name="body"
  26.             android:fillColor="#9FBF3B"
  27.             android:pathData="M140.396,175.489v177.915c0,10.566,8.566,19.133,19.135,19.133h22.633v54.744c0,13.451,10.903,24.354,24.354,24.354c13.451,0,24.355-10.903,24.355-24.354v-54.744h37.371v54.744c0,13.451,10.902,24.354,24.354,24.354s24.354-10.903,24.354-24.354v-54.744h22.633c10.569,0,19.137-8.562,19.137-19.133V175.489H140.396z" />
  28.         <path
  29.             android:name="right_arm"
  30.             android:fillColor="#9FBF3B"
  31.             android:pathData="M372.734,297.598c0,13.45,10.903,24.354,24.354,24.354l0,0c13.45,0,24.354-10.904,24.354-24.354V199.09c0-13.45-10.904-24.354-24.354-24.354l0,0c-13.451,0-24.354,10.904-24.354,24.354V297.598z" />
  32.     </group>
  33. </vector>

我們創建一個<vector> 元素,指定了寬和高,然後創建包含了6個<path>元素的<group>元素。這6個<path>元素的定義非常類似svg中的定義,只有非常小的差別,大部分內容都是直接從svg中copy的。我們還定義了name 屬性來描述每個path的作用。這個文件保存下來仍然只有2412字節。

下面我們可以就像一般drawable一樣去使用上面定義的VectorDrawable了。

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:paddingLeft="@dimen/activity_horizontal_margin"
  6.     android:paddingRight="@dimen/activity_horizontal_margin"
  7.     android:paddingTop="@dimen/activity_vertical_margin"
  8.     android:paddingBottom="@dimen/activity_vertical_margin"
  9.     tools:context=".VectorDrawablesActivity">
  10.  
  11.     <ImageView
  12.         android:id="@+id/android"
  13.         android:layout_width="wrap_content"
  14.         android:layout_height="wrap_content"
  15.         android:src="@drawable/android"
  16.         android:contentDescription="@null" />
  17.  
  18. </RelativeLayout>

運行結果如下:

 simple_vector_drawable-300x169.png

有一個小問題:這個VectorDrawable渲染的非常好,但是我遇到過從其他的svg文件中複製的VectorDrawable 在Android Studio中無法預覽的情況(在真實設備中運行卻是正常的),因此不管Android Studio是否能正常預覽,還是以真實設備爲準吧,Android Studio是有bug的。我用的是V1.0.2 版本,關於這個bug在這裏有描述:here

現在我們可以使用VectorDrawable大幅度的減小我們的apk了,而且這還讓我們在維護app的時候容易的多,至少在使用VectorDrawable的資源上我們不需要因爲要兼容新的設備而修改。這還只是VectorDrawable的一個用處,在後面的文章中我們將看到VectorDrawable是如何動畫的。

這篇文章的代碼可以在這裏得到:here

 

英文原文:https://blog.stylingandroid.com/vectordrawables-part-1/ 

本文由jcodecraeer翻譯,歡迎轉載,請註明出處:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0201/2396.html 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章