前幾天羣成員討論過關於9patch的工具【我比較喜歡喊它9妹子,西西(*^_^*)】、而後研究了一下,比較簡單可是很實用的一個Android sdk 自帶工具、這裏給你們作一個分享下經驗!android
1.什麼是「9妹」(9patch)?canvas
它是一個對png圖片作處理的一個工具,可以爲咱們生成一個"*.9.png"的圖片;編輯器
2.何爲"*.9.png"?工具
所謂"*.9.png"這是Android os裏所支持的一種特殊的圖片格式,用它能夠實現部分拉伸;這種圖片是通過」9妹「進行特殊處理過的,若是不處理的話,直接用PNG圖就會有失真,拉伸不正常的現象出現。字體
3.它的用途是?this
說到用途,這種特殊格式的png圖,我也看了網上的相關文章但都是用一個能自適應的button舉例子!(以下圖)清一色抄襲.. - -、code
(此實例我們直接無視掉,在後面我會給你們灌輸遊戲中實例)orm
這個例子是指當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妹」的好處,下面咱們來看看代碼如何實現此格式的方式和效果吧!
·········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妹」哦