天天看點

android.graphics.Movie-NinePatchNinePatch

  Movie,NinePatch兩個類都内容比較少,都是圖檔相關的,故放在一起翻譯。Movie和Bitmap是一樣的都是用來處理圖檔的,隻不過Movie是專門用來處理gif圖檔的,它沒有Bitmap那麼強大,基本上的功能就是把gif圖檔顯示出來就ok了,它沒有初始化函數,由靜态函數處擷取Movie對象。下面看函數,

public static Movie decodeByteArray (byte[] data, int offset, int length)

public static Movie decodeFile (String pathName)

public static Movie decodeStream (InputStream is)

這三個函數都是用來擷取Movie對象的,使用方法跟BitmapFactory類中定義的同名靜态函數是一樣的。

public void draw(Canvas canvas, float x, float y,Paint paint)

public void draw(Canvas canvas, float x, float y)

在canvas的x,y點(不)使用paint将圖檔畫出來,注意該函數隻能畫出gif動畫的某一幀來,具體某幀由函數setTime确定

public int duration()

該gif動畫有多少幀

public int height()

public int width()

擷取該gif圖檔的寬高

public boolean isOpaque()

判斷圖檔是否為不透明的

public boolean setTime(int relativeMilliseconds)

設定目前為第幾幀用于顯示。

舉例使用

private long mMovieStart=0;

 Movie m1=this.getResources().getMovie(R.drawable.poon);

 Movie m2=this.getResources().getMovie(R.drawable.wancan); 

// InputStream is=this.getContext().getResources().openRawResource(R.drawable.usb);

// Movie m1=Movie.decodeStream(is);

 int duration=m1.duration();

 int duration2=m2.duration();

 if(duration==0)

  duration=1000;

 if(duration2==0)

  duration2=1000;

    long now=android.os.SystemClock.uptimeMillis();

    if(mMovieStart==0)

     mMovieStart=now;

    System.out.println("time="+(now-mMovieStart));

    int index=(int)(now-mMovieStart)%duration;

    int index2=(int)(now-mMovieStart)%duration2;

 m1.setTime(index);

 m1.draw(canvas, 100, 100);

 m2.setTime(index2);

 m2.draw(canvas, 100, 300);

 this.invalidate();

 兩個動畫一起畫,第一個動畫顯示一卡一卡的,第2個動畫更誇張,丢掉了很多幀,看起來很不連貫,不明白為何要通過setTime這種方式來畫,而沒有設定幀數這樣的方法。(ps:最近重看了下代碼,發現一卡一卡的原因,丢掉很多幀的原因是把對檔案的操作放到ondraw函數裡邊去了,這樣每次draw的時候都要先對檔案操作一番,生成movie對象,才會畫出圖檔來,難怪卡成那樣,把對movie的生成放到view的初始化函數裡邊去了之後,動畫一點都不卡了)

Movie隻支援gif格式的圖檔,用它來解碼其它類型的圖檔都會導緻異常。

在搜尋Movie的相關資訊中,發現很多人都提到Movie沒法處理sdcard中的圖檔,我自己試了一下,發現通過

File file=new File("/mnt/sdcard/txt/poon.gif"); 

FileInputStream fi=null;

Movie m2=null;

 try{

  fi=new FileInputStream(file);

 m2=Movie.decodeStream(fi);

 fi.close();

 }catch(Exception e){}

或者直接調用m2=Movie.decodeFile("/mnt/sdcard/txt/poon.gif");

這樣得出來的Movie不是空的,但是畫到螢幕上時什麼都顯示不出來,

檢視了下decodeFile,decodeStream兩個函數的參考代碼,發現兩個函數其實是一個函數,第一個函數代碼實作是依賴第二個函數的

後來我把try裡邊的代碼改了下

 try{

  fi=new FileInputStream(file);

 int len;

 byte array[]=new byte[1024];

 ByteArrayOutputStream baos=new ByteArrayOutputStream(1024);

 while((len=fi.read(array))>0)

 {

  baos.write(array);

 }

 byte buffe[]=baos.toByteArray();

 m2=Movie.decodeByteArray(buffe, 0, buffe.length);

 //m2=Movie.decodeStream(fi);

 fi.close();

 }catch(Exception e){}

這樣gif動畫就可以畫出到螢幕上來了,這就解決了怎麼顯示sdcard中的動畫問題了。

NinePatch

類NinePatch預設将bitmap分成9個部分來畫,其中4個角是不能收縮的,4個邊標明一個軸線來進行收縮,中間部分按同一個軸線來收縮,正常情況下中間部分是透明的,這樣patch能提供一個長方形區域,當圖檔增加的内容超過了它本來的邊界的時候,NinePatch本質上是允許圖檔按照使用者自定義的方式來伸縮。要了解NinePatch的詳細情況,不妨看看2D Graphics的讨論。

Draw 9-Patch工具是一個很有效的建立NinePatch圖檔的工具,用WYSIWYG的圖檔編輯方式。

public NinePatch(Bitmap bitmap, byte[] chunk, String srcName)

初始化函數,用于建立NinePatch對象,第2個參數可以如此擷取,bitmap.getNinePatchChunk();第三個參數一般為null

public void draw(Canvas canvas,Rect location)

public void draw(Canvas canvas,Rect location, Paint paint)

public void draw(Canvas canvas,RectF location)

在location的位置畫出該9patch圖檔。

public int getDensity()

擷取圖檔的density

public int getHeight()

public int getWidth()

擷取寬高度

public final Region getTransparentRegion (Rect location)

擷取圖檔在location位置的透明區域

public final boolean hasAlpha()

判斷圖檔是否有alpha這個值,詳見bitmap的該函數,意義一樣

public static boolean isNinePatchChunk(byte[] chunk)

判斷數組chunk是否為該圖檔的Chunk。

public void setPaint(Paint p)

給該圖檔設定畫筆。

該類的用法要配合android-sdk-windows\tools\draw9patch.bat工具使用,對處理圖檔的拉伸能減小模糊度。

用法請百度,很多例子

繼續閱讀