g公司代碼顯示svg:
SVGParserRenderer drawable = new SVGParserRenderer(context, String svgContent); String svgContent = <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve"> <path fill="#B0B0B0" d="M3.494,24c0-0.587,0.476-1.063,1.063-1.063h38.886c0.588,0,1.063,0.476,1.063,1.063l0,0 c0,0.587-0.475,1.062-1.063,1.062H4.557C3.97,25.063,3.494,24.587,3.494,24L3.494,24z"/> <g><g><g> <path fill="#B0B0B0" d="M3.806,23.249c0.415-0.414,1.088-0.414,1.502,0l17.054,17.053c0.415,0.415,0.415,1.087,0,1.503l0,0 c-0.415,0.414-1.088,0.414-1.503,0L3.806,24.751C3.391,24.336,3.391,23.665,3.806,23.249L3.806,23.249z"/> </g><g> <path fill="#B0B0B0" d="M22.361,6.196c0.415,0.415,0.415,1.087,0,1.502L5.308,24.751c-0.414,0.415-1.087,0.415-1.502,0l0,0 c-0.415-0.415-0.415-1.087,0-1.503L20.858,6.196C21.273,5.781,21.946,5.781,22.361,6.196L22.361,6.196z"/> </g></g></g> </svg> (SVGView )mSvgView.setSVGRenderer(drawable, null); <com.trevorpage.tpsvg.SVGView android:id="@+id/siv_topicon" android:layout_width="@dimen/abs__shortcut_svg_size" android:layout_height="@dimen/abs__shortcut_svg_size" android:layout_gravity="center" > </com.trevorpage.tpsvg.SVGView> public class SVGView extends View {} public class SVGParserRenderer extends DefaultHandler {} SVGView.setSVGRenderer(SVGParserRenderer, null);
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>
Demo附件: mytest.zip
效果圖:
實例二:【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以下版本的。但其的穩定性,以及后續的工作量是需要我們仔細斟酌的問題之一。