> 本文為CSDN學院免費課程[《NinePatch圖片制作從入門到精通》](http://edu.csdn.net/course/detail/351)的筆記,建議新手先觀看視頻,整理此筆記是為了便于自己復習,有NinePatch基礎的朋友可以直接觀看第四部分。—-【轉載請注明出處】
## 一、工具介紹

這是一張PNG圖片,為了方便觀看做的比較大。在Android中使用NinePatch圖片的一般都是很小的圖片,因為當內容多了的時候,背景會自動拉伸來適應內容,而如果圖片做大了,內容少,則圖片也不會自動變小,所以用作NinePatch圖片的png圖片一般是比較小的。
打開Android自帶的NinePatch圖片制作工具(**Android SDK**目錄下的 **/tools/draw9patch.bat**),并且打開上面的圖片,如下:

打開圖片后,在位置1的地方,可以看到圖片的周圍多了1圈1像素大小的透明的點,這就是我們要進行NinePatch圖片制作的地方。
1. 位置1:編輯區。
在這個區域來設置圖片的“拉伸區域”和“內容區域”。注:“拉伸區域”意思是哪個區域是可以進行拉伸的;“內容區域”,如一個Button、TextView,Button中有文字,則這些文字所在的區域即為內容區域。又如一個Linearlayout,這個布局里面的內容顯示的地方也是內容區域。
2. 位置2:拉伸預覽區域。
這是模擬垂直拉伸、水平拉伸、垂直水平都拉伸的3種情況的預覽圖。從上圖中可知,“Zoom”是100%,也就是原圖的編輯區的大小是原圖大小,再看拉伸預覽區域,垂直拉伸時,上下兩條邊的線條寬度被拉高了一倍,因為“Pathch scale”設置的是2x,也就是拉伸為原來的兩倍,垂直拉伸后高度就是原來的兩倍了,水平拉伸后則寬是原來的兩倍了,兩邊都拉伸后則寬高都是原來的兩倍。從上圖可知,水平拉伸后,左右兩條邊的線條寬度比原來寬了一倍,而兩邊都拉伸的預覽圖可知4條邊的線條寬度都被比原來寬了1倍。
3. 位置3:Zoom - 編輯區顯示大小的調整,如果編輯區太小不好編輯,則可以調整這里把編輯區放大
4. 位置4:Patch scale - 拉伸倍數,調整拉伸倍數可以方便的查看拉伸不同倍數后的效果
5. 位置5:Show lock - 顯示鎖定的區域,即不可編輯的區域
6. 位置6:Show patches – 顯示拉伸區域
7. 位置7:Show content – 顯示內容區域
8. 位置8:顯示使用提示信息
## 二、工具實戰
1.把編輯區視圖顯示調大,如下:

2.為了方便查看拉伸后的效果也把拉伸比例調大一些:

3.顯示不可編輯區域,如下圖,當把鼠標移到圖片上時就會顯示不可編輯區域,即紅色框中的區域,現實中最外的紅色框是沒有的,這里加一個紅框只是為了方面觀看,從下圖可看到紅框外由一個像素大小的透明線條圍了起來,這條線條即我們要編輯的區域。

4.顯示會被進行拉伸的區域,如下的粉紅色區域即是會被拉伸的地方,其他的地方將不會被拉伸,也就是說不管怎么拉伸,變的只是粉紅的區域,其他的區域的形狀什么的都不會發生變化:

注:對于會進行拉伸的區域很多人都是這么說的,其實應該用一種更加準確的說法是“粉紅色區域包括粉紅色區域的前后左右的部分都是拉伸部分,其他的才是不會被拉伸的部分,我再加些邊框后效果圖如下:

上圖中粉紅色區域,和它上下左右的4個藍色框區域都是拉伸的區域,其他還有4個紅框的區域則是一直保持不變的區域。從這張圖可看到總共有9個區域,所以稱這樣的圖片為NinePatch圖片。
5.顯示內容區域,如下圖中藍色的區域即內容區域,如一個TextView設置了下面的圖為背景,則文字顯示的區域為下面的藍色區域:

6.畫黑線的快捷方式

如上圖,把鼠標移到編輯區的灰色區域,上、下、左、右都可以,如上圖移到了上方的灰色區域,此時看到了兩條灰色線,拉動這兩條灰色線即可畫出黑線,如下:

如上圖,拖動右邊的線向左拖,發現左邊自動出現了一條黑線,繼續向左方向拖是漸漸的消除這條黑線,如果一直拖到與最左邊的灰色線重合,則這一條黑線都被消除了,如下圖:

經常的情況是我們要自定義的畫出黑色線,也就是可以從任何地方開始畫黑色的線,方式也很簡單,在灰色的地方按下鼠標開始拖動即可,如下:

如上圖是從隨意的一個位置按下鼠標向右拖動拖出來的一斷黑色線。上、下、左、右四條邊的黑色線都可以用類似的方法來畫。當然了,也可以在透明的線上直接點或者拖動來畫黑色線,如下:


如上圖就是在透明的線上隨意位置按下鼠標向右拖動,當松開鼠標時黑色線就出來了。
刪除黑色線,前面說了一種刪除黑色線的方式,也可以使用Shift + 點擊/拖動 來實現,如下:



7.這個知識點抄于網上

點擊這個按鈕,如果有壞的拉伸,則會顯示出紅色。
在拉伸區域周圍用紅色邊框顯示可能會對拉伸后的圖片產生變形的區域,如果完全消除該內容則圖片拉伸后是沒有變形的,也就是說,不管如何縮放圖片顯示都是良好的。 (實際試 發現NinePatch編輯器是根據圖片的顏色值來區分是否為bad patch的,一般來說只要色差不是太大不用考慮這個設置。)
## 三、制作NinePatch圖片實戰
### 3-1 制作拉伸區域
為了方便知道使用NinePatch圖片帶來的好處,這里再使用另一張圖片來進行解講,如下:

這是一個圓角的圖形,因此在進行拉伸時,4個圓角應該保持不變,變的是4條直線。

有時發現打開png圖片后發現四周的透明區域不太規則,不是說只會在原圖形的周圍多一像素的空間而已嗎?這時拉動一下Zoom的比例的可以了,如下圖:

這里我們要實現拉伸時線條的寬度不變,四個圓角不變。很多人在作用NinePatch圖片時都是畫一條一條的黑線,其實是他們沒能夠理解透NinePatch圖片的制作,如這里要達到拉伸時線條的寬度不變、四個轉角不變,只需要點兩個點就夠了,如下:

從上圖的拉伸預覽圖可以看到線條寬度沒變,4個圓角也沒有變。有了前面的理論就容易理解了,在進行水平拉伸時,拉伸的是垂直的那條線的區域,垂直線的兩邊不會被水平拉伸的,如下圖紅框是會被水平拉伸的區域,它的左右兩邊的區域將保持不變:

相應的,垂直拉伸時拉伸的是水平的那條線的區域,這條線的上下兩部分是不會被垂直拉伸,如下圖中的紅色區域會被拉伸:

### 3-2 制作內容區域
如果圖片只是拉伸的功能,上面的知識就夠用了。制作內容區域是可選的,如果你沒有這個需求就不需要制作內容區域。如果這個圖片要用作某些容器的背景,如用作TextView的背景時,TextView中的文字的位置應該是怎樣的呢?
如:公司要求這樣:需要文字是靠矩形的底部對齊的,應該怎樣制作符合這樣要求的NinePatch圖片呢?
這里還是使用上圖的基礎上制作,如下:

如上圖,在下方畫了一條黑錢,則這條黑線就定義了紅框這個區域,當然,上圖中的紅框、藍框是我畫上去的為了方面講解。這樣內容只會出現在紅框中,而不會出現在它左右兩邊的藍框中。從右邊的拉伸預覽圖也可以看到效果,把“Show content”勾上,則拉伸預覽圖就可以看到藍色的區域,這些區域就是文字出現的地方。
接著來設置文字靠矩形的底部對齊,其實這樣說不太對,因為當內容小于NinePatch圖片設置內容區域的高度時,內容就小于內容區域,那這時內容應該顯示在內容區域的哪里呢,這時就要配合gravity來調整。NinePatch圖片編輯如下:

如上圖在右邊畫了一條黑線,這條黑線偏下,它定義了內容在垂直方向的位置是偏下的,底部和右邊這兩條線的交叉部分,如上圖的畫了斜線的紅框即為內容區域,文字將顯示在這個區域。
其實這樣理解內容區域是錯誤的,因為圖片是會進行拉伸的,正確的理解應該是這樣的:底部的黑線和右邊的黑線是給內容設置padding,這樣比較好理解,如上圖設的內容設置用padding來理解如下圖:

在Android的布局的TextView使用這張背景,代碼如下:

效果圖如下:

可看到字體的左右是有一些padding,而上下是方向的padding則是上方的比較大,看起來就像是文字在底部對齊一樣。因此,NinePatch圖片做的好,連TextView在布局中的padding設置都省了。
## 四、學習例子
更多的NinePatch圖片的制作例子,可查看AndroidSDK目錄下的圖片,如:`sdk\platforms\android-19\data\res\drawable-ldpi`,使用搜索查找NinePatch圖片,然后看官網的圖片都是怎么點這些黑線的,有什么值得學習的,為什么別人這么點?多看,對于理解NinePatch圖片的制作一定大有幫助的,搜索結果如下圖:

1.如用ps打開這張圖片:
放大:

從這張圖片可以看到左邊、上邊都點了兩個黑點,他的意圖是什么呢?通過上面的學習分析,它這就是設置了拉伸區域在圖形中間的加號的四周,即不管怎么拉伸,圖形中間的加號是不會變大、變形的,也就是不會發生改變的。又如下面的圖是為了保持中間的減號不被拉伸:

2.

3.如果某個NinePatch圖片你看不明白他的意圖,則可以把它復制到你的Android項目中,然后使用它,看看是什么效果即可知其意圖。如有一張這樣的NinePatch圖片:

你想象不到使用它會是什么效果吧?這就是人家的高招,如果你不去看別人的,你自己就不會懂得像人家這樣去制作NinePatch圖片,所以要多看,如應用上圖的NinePatch圖片效果如下:

4.看下面兩張這樣的NinePatch圖片:


它就是一條透明灰色的水平線,和一條黑色的垂直線,沒有必要做成NinePatch啊,為什么呢?
使用這條線看看什么效果,如下:

很經典的一條線,所以需要用到這條線時,我們為何還要自己去制作呢,直接使用:`android:background="@android:drawable/menu_separator"`,這樣做需要注意,可能在不同的版本這條線可能顯示效果不一樣。
5.

這張就是保留發光的光暈不會被拉伸,拉伸的是中間白色的區域。文字內容也只會出現在白色區域。
6.

這張是為了保留右邊的箭頭不被拉伸。
7.

看著是個橢圓,使用后效果為:

8.再看看這些NinePatch圖片的意圖是什么?

答:這張圖片也很高明,放大鏡永遠不會被拉伸,水平方向的拉伸是頂部右邊的那個點,關鍵是垂直拉伸了,這是左邊的那個點,拉伸的是這個點,而這個點是透明的,所以垂直拉伸時不會對下面有顏色的圖片的形狀有影響。
9.再來看這張,完全無法想象使用后會是什么效果,只能實際使用去直觀的看了:

用作TextView的背景后為:

10.

這是**scrollbar_handle_vertical.9.png**,使用在**imageView**后為:

看上圖NinePatch圖片的兩邊明明是透明度比較高呀,可效果為什么是邊線的顏色比較深?
11.還有這么小的NinePatch圖片:


btn_default_transparent_normal.9.png
使用后的效果為:(真美!)

12.再看這個透明的NinePatch圖片又有什么意圖:

使用的效果為:

看了效果才明白其意圖,就是圖片就設置好了paddingLeft的,如下調用View的寬度后的效果:

不理解原理的人,以為下面的點就是內容區域,就會認為內容應該顯示在圖片的右邊,實際上不是,跟據前面所學,下面的點是設置padding的,也就是paddingLeft是固定的矩離,如下圖:

如果是這樣的話,那paddingRight就是0,所以我們在保持長度不變的情況下增加文字,如下:

哈哈,證明了我的猜想是對的呀!!
如果NinePatch圖片真的是設置了paddingLeft的值的話,那我在代碼中把paddingLeft設置為0,看看效果:

猜想是對的!!!學習只用腦子想是不是對的,不要猜想,要用實踐去證明!!
13.再來看一張使用相同原理的圖:

效果為:

這達到了drawableRight的效果,并且圖片已經是和文字居中的。
14.



看著像是個圓形,其實他它是個圓角矩形,真是想不到啊!做圖的人太牛了!把圖片的容量做到了最小,節省apk的大小啊!
15.再來看這張又有什么高明之處呢?
divider_horizontal_dark.9.png

不知道高明在哪里。但相信Google的人不會這么無聊的,肯定有高明的地方。


這個就一像素的顏色,更加不明白其意圖何在。
此時想我起我曾經在用友面試時,一位技術官問我,在ListView中是使用圖片做分隔線好還是直接使用Shape圖形好,技術官后來說是使用圖片的好,因為Android的圖形渲染機制不夠好,如果直接使用Shape效率就會比較低、比較耗內存。這樣可以解釋為我們盡量的使用圖片,而不要直接使用代碼來畫圖形。
16.

這個就是為了圖片的圖形保持不變,如果只是這樣那在使用圖片時用wrapcontent即可,它這樣做又會帶來什么好處?答:為了可以使背景圖片適應任何的控件大小,而且保持圖形大小不變。適應大小是為了使點擊事件更容易發生,因為控件大的話點中的機率就會大。
最后 再次感謝錄制視頻的老師!