前幾天群成員討論過關於9patch的工具【我比較喜歡喊它9妹子,西西(*^_^*)】、然後研究了一下,比較簡單但是很實用的一個Android sdk 內建工具、這裡給大家做一個分享下經驗!
1.什麼是“9妹”(9patch)?
它是一個對png圖片做處理的一個工具,能夠為我們產生一個"*.9.png"的圖片;
2.何為"*.9.png"?
所謂"*.9.png"這是Android os裡所支援的一種特殊的圖片格式,用它可以實現部分展開;這種圖片是經過”9妹“進行特殊處理過的,如果不處理的話,直接用PNG圖就會有失真,展開不正常的現象出現。
3.它的用途是?
說到用途,這種特殊格式的png圖,我也看了網上的相關文章但都是用一個能自適應的button舉例子!(如)清一色抄襲.. - -、
(此執行個體咱們直接無視掉,在後面我會給大家灌輸遊戲中執行個體)
這個例子是指當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圖片預設周圍多了一像素點,也就是這一圈一像素點就是咱們的可操作地區。但是因為下方和右方可操作地區屬於可選地區,不用理會;主要大家注意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妹”的好處,下面我們來看看代碼如何?此格式的方式和效果吧!
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
package com.himi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.NinePatch; import android.graphics.Paint; import android.graphics.RectF; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class MySurfaceView extends SurfaceView implements Callback, Runnable { private Thread th = new Thread(this); private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private Bitmap bmp_old; private Bitmap bmp_9path; private NinePatch np; public MySurfaceView(Context context) { super(context); this.setKeepScreenOn(true); bmp_old = BitmapFactory.decodeResource(getResources(), R.drawable.himi_old); bmp_9path = BitmapFactory.decodeResource(getResources(), R.drawable.himi_9path); np = new NinePatch(bmp_9path, bmp_9path.getNinePatchChunk(), null); //建立一個ninePatch的對象執行個體,第一個參數是bitmap、第二個參數是byte[],這裡其實要求我們傳入 //如何處理展開方式,當然我們不需要自己傳入,因為“.9.png”圖片自身有這些資訊資料, //也就是我們用“9妹”工具操作的資訊! 我們直接用“.9.png”圖片自身的資料調用getNinePatchChunk()即可 //第三個參數是圖片源的名稱,這個參數為選擇性參數,直接null~就OK~ sfh = this.getHolder(); sfh.addCallback(this); paint = new Paint(); paint.setAntiAlias(true); setFocusable(true); } public void surfaceCreated(SurfaceHolder holder) { Log.v("Himi", "surfaceCreated"); th.start(); } /** * @author Himi */ public void draw() { canvas = sfh.lockCanvas(); canvas.drawColor(Color.BLACK); RectF rectf_old_two = new RectF(0, 50, bmp_old.getWidth() * 2, 120 + bmp_old.getHeight() * 2);//備忘1 RectF rectf_old_third = new RectF(0, 120 + bmp_old.getHeight() * 2, bmp_old.getWidth() * 3, 140 + bmp_old.getHeight() * 2 + bmp_old.getHeight() * 3); // --------下面是對正常png繪畫方法----------- canvas.drawBitmap(bmp_old, 0, 0, paint); canvas.drawBitmap(bmp_old, null, rectf_old_two, paint); canvas.drawBitmap(bmp_old, null, rectf_old_third, paint); RectF rectf_9path_two = new RectF(250, 50, 250 + bmp_9path.getWidth() * 2, 90 + bmp_9path.getHeight() * 2); RectF rectf_9path_third = new RectF(250, 120 + bmp_9path.getHeight() * 2, 250 + bmp_9path.getWidth() * 3, 140 + bmp_9path.getHeight() * 2 + bmp_9path.getHeight() * 3); canvas.drawBitmap(bmp_9path, 250, 0, paint); // --------下面是".9.png"映像的繪畫方法----------- np.draw(canvas, rectf_9path_two); np.draw(canvas, rectf_9path_third); sfh.unlockCanvasAndPost(canvas); } public void run() { // TODO Auto-generated method stub while (true) { draw(); try { Thread.sleep(100); } catch (Exception ex) { } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v("Himi", "surfaceChanged"); } public void surfaceDestroyed(SurfaceHolder holder) { Log.v("Himi", "surfaceDestroyed"); } }
是模擬器中的、
左邊是正常png的縮放不同大小的情況,右邊是咱們的9妹處理過的“*.9.png”、娃哈哈,怎麼樣 效果明顯不一樣吧!
好啦,到這裡就結篇吧,挺累的寫了三個多小時了....... 希望大家以後多多的利用 “9妹”哦、
(推薦大家訂閱本部落格,因為咱的更新速度可是很快的~娃哈哈)