關於Android中使用SVG特性的探索與總結
前言
引入SVG還需要從圖片的數字化說起。一般來說,將圖片儲存為資料有兩種方案。其一、就是我們傳統使用的點陣圖(光柵圖)。即將圖片看成在平面上密集排布的點的集合。每個點發出的光有獨立的頻率和強度,反映在視覺上,就是顏色和亮度。點陣圖擁有一個龐大的家族,包括常見的JPEG/JPG, GIF, TIFF, PNG, BMP等。第二種方案就是向量圖(SVG就是其中的一種)。它用抽象的視角看待圖形,記錄其中展示的模式而不是各個點的原始資料。它將圖片看成各個“物件”的組合,用曲線記錄物件的輪廓,用某種顏色的模式描述物件內部的圖案(如用梯度描述漸變色)。比如一張留影,被看成各個人物和背景中各種景物的組合。這種更高階的視角,正是人類看世界時在意識裡的反映。向量圖格式有CGM, SVG, AI (Adobe Illustrator), CDR (CorelDRAW), PDF, SWF, VML等等。
向量圖中簡單的幾何圖形,只需要幾個特徵數值,就可以確定。比如三角形,只需要確定三個頂點的座標。圓只需要確定圓心的座標和半徑。描述它的函式已知的曲線也只需要幾個引數就能夠確定。如正弦曲線、各種螺線等等。如果用點陣圖記錄這些幾何圖案,則需要包含組成線條的各個畫素的資料。除了大大節省空間,向量圖還具有完美的伸縮性。因為記錄的是圖形的特徵,圖形的尺寸任意變化時,都只是做著相似變換,不會出現模糊和失真。相反,點陣圖的圖片放大到超出原有大小時,各個畫素點之間出現空缺,即使用某種演算法填充,也會出現模糊鋸齒等現象,不如向量圖精確。因而向量圖很適合用於記錄諸如符號、圖示等簡單的圖形。而點陣圖則適合於沒有明顯規律的、顏色豐富細膩的圖片。
說起SVG可能有些人不怎麼熟悉,但提及xml,對於大部分人來說都是耳熟能詳的。其實,SVG也就是使用xml定義的圖形。當然,主流的解析xml的工具一般都可以拿來解析svg。SVG是從Android5.0版本開始被引入到Android平臺上的。下面我就SVG的話題,根據我這段時間的探索程序一一展開。
一、SVG簡介
根據網路上的定義:SVG是可縮放向量圖形,是基於可擴充套件標記語言(標準通用標記語言的子集),用於描述二維向量圖形的一種圖形格式。它由全球資訊網聯盟制定,是一個開放標準。
SVG的優勢
首先簡要解釋一下向量影象格式和點陣圖影象格式的區別。向量影象用點和線來描述物體,所以檔案會比較小,同時也能提供高清晰的畫面,適合於直接列印或輸出。而點陣圖影象的儲存單位是影象上每一點的畫素值,因此一般的影象檔案都很大,會佔用大量的網路頻寬。SVG是一種向量圖形格式,GIF、JPEG是光柵檔案格式。有了兩者的概念後,SVG較GIF、JPEG的優勢顯而易見。
任意放縮
使用者可以任意縮放影象顯示,而不會破壞影象的清晰度、細節等。
文字獨立
SVG影象中的文字獨立於影象,文字保留可編輯和可搜尋的狀態。也不會再有字型的限制,使用者系統即使沒有安裝某一字型,也會看到和他們製作時完全相同的畫面。
較小檔案
總體來講,SVG檔案比那些GIF和JPEG格式的檔案要小很多,因而下載也很快。
超強顯示效果
SVG影象在螢幕上總是邊緣清晰,它的清晰度適合任何螢幕解析度和列印解析度。
超級顏色控制
SVG影象提供一個1 600萬種顏色的調色盤,支援ICC顏色描述檔案標準、RGB、線X填充、漸變和蒙版。
互動和智慧化
SVG面臨的主要問題一個是如何和已經佔有重要市場份額的向量圖形格式Flash競爭的問題,另一個問題就是SVG的本地執行環境下的廠家支援程度。
二、SVG的解析
上文提到Android5.0時引入了SVG特性,其中必然會涉及到SVG圖片的載入與解析。而svg本質上就是xml檔案,所以從解析角度來看,能解析xml檔案的工具應該幾乎都可以用來解析svg檔案。
1、DOM解析
檢視Android原始碼可以看出,5.0引入svg後並沒有使用dom進行解析svg原始檔,雖然svg號稱完全支援dom標準。筆者從dom解析的過程可以看出,Dom解析是將xml檔案全部載入,組裝成一顆dom樹,然後通過節點以及節點之間的關係來解析xml檔案。雖然一般情況下,svg檔案是比較小的,但也不乏有些很複雜的圖片會上升到M級別,如果在解析時需要全部載入,對於Android系統來說時比較耗時的,這也許就是dom遭Android淘汰的原因之一吧。
2、SAX解析
SAX(Simple API for XML)解析器是一種基於事件的解析器,它的核心是事件處理模式,主要是圍繞著事件源以及事件處理器來工作的。當事件源產生事件後,呼叫事件處理器相應的處理方法,一個事件就可以得到處理。在事件源呼叫事件處理器中特定方法的時候,還要傳遞給事件處理器相應事件的狀態資訊,這樣事件處理器才能夠根據提供的事件資訊來決定自己的行為。SAX解析器的優點是解析速度快,佔用記憶體少。非常適合在Android移動裝置中使用
3、PUll解析
PULL解析器的執行方式和SAX類似,都是基於事件的模式。不同的是,在PULL解析過程中,我們需要自己獲取產生的事件然後做相應的操作,而不像 SAX那樣由處理器觸發一種事件的方法,執行我們的程式碼。PULL解析器小巧輕便,解析速度快,簡單易用,非常適合在Android移動裝置中使 用,Android系統內部在解析各種XML時也是用PULL解析器
三、SVG在Android5.0以上版本中的使用
1、使用方法
鑑於SVG有那麼多的優點,Android於5.0版本將該特性引入。在5.0以上版本中使用方法如下:
1)獲取SVG圖片資料
第一種方法當然是從網上down了(一般直接用來測試使用),這裡只給出幾個常用素材下載網站:
http://sc.chinaz.com/
http://www.freevectors.net
http://www.freevectordownload.com/
其次就是手工製作了:真正做專案時,方法1肯定滿足不了相應的需要了。這時我們只能自己動手來作圖了(應該是美工來負責^_^||),相應最常用的軟體就是PS、AI或者CDR也可以。具體制作方法這裡就不做介紹了,直接上網搜就行。這裡給出一個較為詳細的例子:http://blog.csdn.net/tianjian4592/article/details/44733123
2)將普通SVG圖片資料轉換成Android可用資料
一般的SVG圖片資料是直接在html或jsp中可以使用,Android中若想使用svg則需要中間環節先轉換成Vector標籤包括的xml檔案(如果做動畫的話,外面還需要包括一層animated-vector來引用vector資源),其中最重要的就是path元素,該元素就是圖片載入顯示過程中的繪製軌跡。具體轉換方法網上查詢得出有兩種:一是手動改寫,二是直接使用自動轉化工具轉換(http://inloop.github.io/svg2android/)。具體轉換規則以及相應符號意義可以參見:http://www.w3.org/TR/SVG11/paths.html#PathData.
3)在工程中使用
svg在5.0以上的Android工程中使用相對較為簡單,直接用drawable控制元件(如mageView等)引用第二步中轉換得來的xml檔案資源即可。
2、Demo例項
例項一:mytest(使用Drawable控制元件引用5.0新特性vector資源)
【關鍵程式碼摘要】
使用vector標籤包括path元素
[ sharp_rect.xml ]
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="180dp"
android:height="320dp"
android:viewportWidth="180"
android:viewportHeight="400">
<path
android:name="sharp_rect"
android:fillColor="#000000"
android:pathData="M 320,180 L 0,320 0,0 180,0 z" />
</vector>
使用ImageView引用vector資源sharp_rect
[ activity_main.xml ]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<ImageView
android:src="@drawable/sharp_rect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
例項二:【VectorCard】使用5.0新特性animated-vector標籤引用xml中的svg path元素
【關鍵程式碼摘要】
[ to_stop.xml ]
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:interpolator/decelerate_cubic"
android:propertyName="pathData"
android:valueType="pathType"
android:repeatMode="reverse"
android:repeatCount="1"
android:valueFrom="M100,100 L400,250 L100,400 L100,400 z"
android:valueTo="M100,100 L400,100 L400,400 L100,400 z" />
[ animated_play.xml ]
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/play_icon">
<target
android:animation="@animator/to_stop"
android:name="play" />
</animated-vector>
Demo附件: app.zip
效果圖:
3、小結
Android5.0關於這塊新特性的新增主要是依賴於Vctor,對應的類為VectorDrawable以及AnimatedVectorDrawable。前者主要用於向量圖的載入,後者主要用於向量動畫的載入。二者在使用過程中要區分對待。
四、Android5.0以下使用SVG探索總結
經過這短時間的不斷摸索與實驗,按照svg_android組織的方法主要有以下兩種:
1、基於svg_android庫
抽取類似svg_android庫中適合5.0以下的,且可以解析svg的java檔案,自定義類似svg的控制元件,進行Android工程的搭建(該例項使用sax解析svg檔案)。
對應例項:【SVGMapView-master】
Demo附件: SVGMapView-master.zip
效果圖:
【說明】 該方法需要開發者自己去重寫解析函式,目前該例項並不能支援所有的svg語法的解析,如將該方法佈置到專案中,需要大量拓展解析甚至載入SVg的功能函式。
2、基於JNI技術
載入及加息svg的工作交給C/C++處理,上層使用java呼叫對應.so庫暴露的介面。
對應例項:【ImageViewSvg】
Demo附件: ImageViewSvg.zip
效果圖:
【說明】該方案雖然使用了JNI技術來載入並解析svg檔案,但目前其解析度有限,功能較為單一,如需要佈置該方案於專案中,對於jni側也需要擴充套件大量的svg解析函式。且需要優化對應的載入處理環節。
五、總結
從整體上看,目前是有可能將svg應用到Android5.0以下版本的。但其的穩定性,以及後續的工作量是需要我們仔細斟酌的問題之一。