前幾天羣成員討論過關於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
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(0, 50, bmp_old.getWidth() * 2, 120 + bmp_old.getHeight() * 2);//備註1
49. RectF rectf_old_third = new RectF(0, 120 + 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, 0, 0, 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(250, 50, 250 + bmp_9path.getWidth() * 2, 90 + bmp_9path.getHeight() * 2);
56. RectF rectf_9path_third = new RectF(250, 120 + bmp_9path.getHeight() * 2, 250 + bmp_9path.getWidth() * 3,
57. 140 + bmp_9path.getHeight() * 2
58. + bmp_9path.getHeight() * 3);
59. canvas.drawBitmap(bmp_9path, 250, 0, 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妹”哦、
(推薦大家訂閱本博客,因爲咱的更新速度可是很快的~娃哈哈)