關於安卓9patch圖片的探究


  1.什么是“9妹”(9patch)?

它是一個對png圖片做處理的一個工具,能夠為我們生成一個"*.9.png"的圖片;

  2.何為"*.9.png"?

所謂"*.9.png"這是Android os里所支持的一種特殊的圖片格式,用它可以實現部分拉伸;這種圖片是經過”9妹“進行特殊處理過的,如果不處理的話,直接用PNG圖就會有失真,拉伸不正常的現象出現。

  3.它的用途是?

       說到用途,這種特殊格式的png圖,我也看了網上的相關文章但都是用一個能自適應的button舉例子!(如下圖)清一色抄襲.. - -、

        Draw 9-Patch(3gqa.com)  (此實例咱們直接無視掉,在后面我會給大家灌輸游戲中實例)

 這個例子是指當button上的字體大小改變,那么文字底下的png圖也會自動適應文字。

 這似乎表明做Android 軟件應用 使用一些組件的的時候會時常用到;

       4.那么實際在游戲中到底如何使用呢?什么情況下去使用呢?

   ....當然啦,身為做游戲我一定要”9妹“利用在咱們游戲中才行,不然豈不是白研究了、經過思考突然想到了一些情況,並且發現“9妹”確實在游戲開發中占有一定的分量!下面我們來先熟習“9妹”工具,然后再跟大家舉例,貼圖來說明其用途、畢竟有圖有真相 呵呵~

 

啟動9妹:

在你Android SDK 路徑下 X:/android sdk/tools ,你會找到一個 【draw9patch.bat】,沒錯這就是9妹啦、官方名 NinePatch ;

         

 

提示導入一張png圖片,然后真正進入"9妹"的操作界面(如下圖):     (圖1)

 

      

 

 

序列 ① :在拉伸區域周圍用紅色邊框顯示可能會對拉伸后的圖片產生變形的區域,如果完全消除該內容則圖片拉伸后是沒有變形的,也就是說,不管如何縮放圖片顯示都是良 好的。 (實際試 發現NinePatch編輯器是根據圖片的顏色值來區分是否為bad patch的,一邊來說只要色差不是太大不用考慮這個設置。) 

序列 ② :區域是導入的圖片,以及可操作區域。

序列 ③ :這里 zoom:的長條bar 是對導入的圖放大縮小操作,這里的放大縮小只是為了讓使用者更方便操作,畢竟是對像素點操作比較費眼,下面的 patch scale 是序列 ④區域中的三種形態的拉伸后的一個預覽操作,可以看到操作后的圖片拉伸后的效果。

序列 ④: 區域這里從上到下,依次為:縱向拉伸的效果預覽、橫向拉伸的效果預覽,以及整體拉伸的效果預覽

序列 ⑤: 這里如果你勾選上,那么當你鼠標放在 ② 區域內的時候並且當前位置為不可操作區域就會出現lock的一張圖,就是顯示不可編輯區域 ;

序列 ⑥: 這里勾選上,那么在④ 區域中你就會看到當前操作的像素點在拉伸預覽圖中的相對位置和效果。

序列 ⑦: 在編輯區域顯示圖片拉伸的區域;

 

如何操作:

                   鼠標左鍵選取需要拉伸的像素點;  shift+鼠標左鍵取消當前像素點。

 

 

操作區域:

                                    

     大家看到導入的png圖片默認周圍多了一像素點,也就是這一圈一像素點就是咱們的可操作區域。因為方和右方可操作區域是指定內容的顯示區域,屬於可選區域,可不予理會;但是要注意內容區域的標記不能有間斷,也就是說標記要連續且僅有一處,否則.9.png圖片在放入項目下會報錯。

      主要大家注意Left 和 top 操作區域;

 

     Top操作區域的一排像素點,表示橫向拉伸的像素點; 

     Left操作區的一排像素點,表示縱向拉伸的像素點;

 

 

下圖是我對圖片的操作:

                                           (圖2)

      

 

 

大家看到上方和左邊的黑色像素了么?對,這些是我手動操作的地方,我這里是想讓此png圖像拉伸操作的時候,只是中間區域被拉伸。選擇上方中間區域是為了橫向拉伸的時候選取的拉伸像素點,左邊則是縱向拉伸的;

  

那么大家現在回頭看一眼(圖1)然后對比(圖2),看到區別了吧!很明顯,(圖1)我們沒有任何操作,默認整體拉伸,那么拉伸的效果很明顯的失真了...而(圖2)我們指定了拉伸的像素點所以只是中間的被拉伸,圖片的花邊我們保留不拉伸這樣看起來就好太多啦 娃哈哈、

然后通過“9妹”就可以保存出來一張“*.9.png”圖片,我們放在android 項目的res 下的 drawable 下就可以拉!

 

現在我就可以跟大家講下使用“*.9.png”的好處:

 

  在我們手機游戲開發的過程中,我們最關系的是生成的安裝文件、比如j2me 的jar 包,塞班的sis、sisx 以及咱們andrid中的apk都希望打包后的包越小越好、雖然現在的手機趨向於智能了,但是畢竟手機的容量和內存還是有限、身為移動設備開發者的我們對此都很看重,那么通過"9妹"處理后的圖片我們就可以省去不少的內存和容量。

  1. 省精力和時間!

    如果我們有一張50*50的類似上面那種帶花邊的png圖片,那么我們在android或者大分辨率的機器上使用的畫,肯定需要對其處理,那么要不就是讓美工的mm們給咱們重新做一張,那么通過"9妹"處理得到的“*.9.png”就會省去美工的負擔了。

  2.省內存!

   如果不想用代碼來對其小圖進行縮放來再次使用(因為考慮會失真),那么可能會多加了圖片,這樣一來游戲包的大小就會增加了,幾K—幾十K不等,而利用"9妹"處理的就省去了這些麻煩。

  3.減少代碼量! 

  有些童鞋該說啦,我用代碼一樣能實現(圖2)的效果不失真,OK,我也知道。當初我在J2ME平台做RPG的時候也是利用設置可視區域等代碼來實現的,但是如果你用“.9.png”的方式就更簡單!!!

 

不多吹 “9妹”的好處,下面我們來看看代碼如何實現此格式的方式和效果吧!

 

  

[java:showcolumns] view plaincopy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. package com.himi;  
  2. import android.content.Context;  
  3. import android.graphics.Bitmap;  
  4. import android.graphics.BitmapFactory;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.NinePatch;  
  8. import android.graphics.Paint;  
  9. import android.graphics.RectF;  
  10. import android.util.Log;  
  11. import android.view.SurfaceHolder;  
  12. import android.view.SurfaceView;  
  13. import android.view.SurfaceHolder.Callback;  
  14. public class MySurfaceView extends SurfaceView implements Callback, Runnable {  
  15.     private Thread th = new Thread(this);  
  16.     private SurfaceHolder sfh;  
  17.     private Canvas canvas;  
  18.     private Paint paint;  
  19.     private Bitmap bmp_old;  
  20.     private Bitmap bmp_9path;  
  21.     private NinePatch np;  
  22.     public MySurfaceView(Context context) {  
  23.         super(context);  
  24.         this.setKeepScreenOn(true);  
  25.         bmp_old = BitmapFactory.decodeResource(getResources(), R.drawable.himi_old);  
  26.         bmp_9path = BitmapFactory.decodeResource(getResources(), R.drawable.himi_9path);  
  27.         np = new NinePatch(bmp_9path, bmp_9path.getNinePatchChunk(), null);  
  28.         //創建一個ninePatch的對象實例,第一個參數是bitmap、第二個參數是byte[],這里其實要求我們傳入  
  29.         //如何處理拉伸方式,當然我們不需要自己傳入,因為“.9.png”圖片自身有這些信息數據,  
  30.         //也就是我們用“9妹”工具操作的信息! 我們直接用“.9.png”圖片自身的數據調用getNinePatchChunk()即可  
  31.         //第三個參數是圖片源的名稱,這個參數為可選參數,直接null~就OK~  
  32.         sfh = this.getHolder();  
  33.         sfh.addCallback(this);  
  34.         paint = new Paint();  
  35.         paint.setAntiAlias(true);  
  36.         setFocusable(true);  
  37.     }  
  38.     public void surfaceCreated(SurfaceHolder holder) {  
  39.         Log.v("Himi""surfaceCreated");  
  40.         th.start();  
  41.     }  
  42.     /** 
  43.      * @author Himi 
  44.      */  
  45.     public void draw() {  
  46.         canvas = sfh.lockCanvas();  
  47.         canvas.drawColor(Color.BLACK);  
  48.         RectF rectf_old_two = new RectF(050, bmp_old.getWidth() * 2120 + bmp_old.getHeight() * 2);//備注1  
  49.         RectF rectf_old_third = new RectF(0120 + bmp_old.getHeight() * 2, bmp_old.getWidth() * 3,  
  50.                 140 + bmp_old.getHeight() * 2 + bmp_old.getHeight() * 3);  
  51.         // --------下面是對正常png繪畫方法-----------  
  52.         canvas.drawBitmap(bmp_old, 00, paint);  
  53.         canvas.drawBitmap(bmp_old, null, rectf_old_two, paint);  
  54.         canvas.drawBitmap(bmp_old, null, rectf_old_third, paint);  
  55.         RectF rectf_9path_two = new RectF(25050250 + bmp_9path.getWidth() * 290 + bmp_9path.getHeight() * 2);  
  56.         RectF rectf_9path_third = new RectF(250120 + bmp_9path.getHeight() * 2250 + bmp_9path.getWidth() * 3,  
  57.                     140 + bmp_9path.getHeight() * 2  
  58.                 + bmp_9path.getHeight() * 3);  
  59.         canvas.drawBitmap(bmp_9path, 2500, paint);  
  60.         // --------下面是".9.png"圖像的繪畫方法-----------  
  61.         np.draw(canvas, rectf_9path_two);  
  62.         np.draw(canvas, rectf_9path_third);  
  63.         sfh.unlockCanvasAndPost(canvas);  
  64.     }  
  65.     public void run() {  
  66.         // TODO Auto-generated method stub  
  67.         while (true) {  
  68.             draw();  
  69.             try {  
  70.                 Thread.sleep(100);  
  71.             } catch (Exception ex) {  
  72.             }  
  73.         }  
  74.     }  
  75.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  76.         Log.v("Himi""surfaceChanged");  
  77.     }  
  78.     public void surfaceDestroyed(SurfaceHolder holder) {  
  79.         Log.v("Himi""surfaceDestroyed");  
  80.     }  
  81. }  

 

 

下圖是模擬器中的效果圖、

 

 

                       

 

左邊是正常png的縮放不同大小的情況,右邊是咱們的9妹處理過的“*.9.png”、娃哈哈,怎么樣  效果明顯不一樣吧!

 

 

好啦,到這里就結篇吧,挺累的 寫了三個多小時了....... 希望大家以后多多的利用 “9妹”哦、

 

(推薦大家訂閱本博客,因為咱的更新速度可是很快的~娃哈哈)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM