- Android Studio開發實戰:從零基礎到App上線(第2版)
- 歐陽燊
- 3922字
- 2019-12-06 12:07:17
2.4 圖形基礎
本節介紹Android圖形的基本概念和幾種常見圖形的使用方法,主要包括狀態列表圖形StateListDrawable的定義與使用、形狀圖形ShapeDawable的定義與使用、九宮格圖片(點九圖片)的制作與適用場景等。
2.4.1 圖形Drawable
Android把所有顯示出來的圖形都抽象為Drawable(可繪制的)。這里的圖形不止是圖片,還包括色塊、畫板、背景等。
drawable文件放在res目錄的各個drawable目錄下。\res\drawable一般存放的是描述性的XML文件,圖片文件一般放在具體分辨率的drawable目錄下。例如:
- drawable-ldpi里面存放低分辨率的圖片(如240×320),現在基本沒有這樣的智能手機了。
- drawable-mdpi里面存放中等分辨率的圖片(如320×480),這樣的智能手機已經很少了。
- drawable-hdpi里面存放高分辨率的圖片(如480×800),一般對應4英寸~4.5英寸的手機(但不絕對,同尺寸的手機有可能分辨率不同,手機分辨率就高不就低,因為分辨率低了屏幕會有模糊的感覺)。
- drawable-xhdpi里面存放加高分辨率的圖片(如720×1280),一般對應5英寸~5.5英寸的手機。
- drawable-xxhdpi里面存放超高分辨率的圖片(如1080×1920),一般對應6英寸~6.5英寸的手機。
- drawable-xxxhdpi里面存放超超高分辨率的圖片(如1440×2560),一般對應7英寸以上的平板電腦。
基本上,分辨率每加大一級,寬度和高度就要加大二分之一或三分之一像素。如果各目錄存在同名圖片,Android就會根據手機的分辨率分別適配對應文件夾里的圖片。在開發App時,為了兼容不同的手機屏幕,根據需求在各目錄存放不同分辨率的圖片才能達到最合適的顯示效果。例如,在drawable-hdpi放了一張背景圖片bg.png(分辨率480×800),其他目錄沒放,使用分辨率480×800的手機查看該App沒有問題,但是使用分辨率720×1280的手機查看App會發現背景圖片有點模糊,原因是Android為了讓bg.png適配高分辨率的屏幕,把bg.png拉伸到了720×1280,拉伸的后果是圖片變得模糊。
開發者拿到一張圖片,可以直接復制粘貼到drawable目錄,也可以通過批量drawable插件Android Postfix Completion生成并導入各分辨率的圖片,該插件的安裝和使用方法參見第1章的“1.5.3 安裝常用插件”。
在XML布局文件中引用drawable文件可使用“@drawable/***”這種形式,如background屬性、ImageView和ImageButton的src屬性、TextView和Button的drawableTop系列屬性都可以引用drawable文件。
在代碼中引用drawable文件可分為兩種情況:
(1)使用setBackgroundResource和setImageResource方法,可直接在參數中指定drawable文件的資源ID,例如“R.drawable.***”。
(2)使用setBackgroundDrawable、setImageDrawable和setCompoundDrawables等方法,參數是Drawable對象,這時得先從資源文件中生成Drawable對象,示例代碼如下:
// 從資源庫里的圖片文件apple.png獲取圖形對象 Drawable drawable = getResources().getDrawable(R.drawable.apple);
2.4.2 狀態列表圖形
一般drawable是靜態圖形,如Button按鈕的背景在正常情況下是凸起的,在按下時是凹陷的,從按下到彈起的過程,用戶便能知道點擊了這個按鈕。根據不同的觸摸情況變更圖形顯示,這種情況會用到Drawable的一個子類StateListDrawable,該子類在XML文件中定義不同狀態時呈現圖形列表。要想在項目中創建狀態圖形的XML文件,則需右擊drawable目錄,然后在右鍵菜單中依次選擇New→Drawable resource file,即可自動生成一個空的XML文件。
下面是一個狀態列表圖形的drawable文件:

該XML定義文件中的關鍵點是state_pressed,值為true表示按下時顯示button_pressed圖像,其余情況顯示button_normal圖像。
為方便理解,接下來我們先將Button控件的background屬性設置為該drawable文件,然后在屏幕上點擊這個按鈕,看看按下和彈起時分別呈現什么效果,界面如圖2-21(按下按鈕)、圖2-22(按鈕彈起)所示。

圖2-21 按下按鈕時的背景樣式

圖2-22 按鈕彈起時的背景樣式
StateListDrawable不僅用于Button控件,而且可以用于其他擁有不同狀態的控件,取決于開發者對StateListDrawable狀態類型的定義。狀態類型的取值說明見表2-9。
表2-9 狀態類型的取值說明

2.4.3 形狀圖形
前面講到可在XML文件中描述狀態列表圖形的定義,還有一種常用的XML圖形文件,是描述形狀定義的圖形—— shape圖形。用好shape可以讓App頁面不再呆板,還可以節省美工不少工作量。
形狀圖形的定義文件以shape元素為根節點。根節點下定義了6個節點:corners(圓角)、gradient(漸變)、padding(間隔)、size(尺寸)、solid(填充)、stroke(描邊),各節點的屬性值主要是長寬、半徑、角度以及顏色。下面是形狀圖形各個節點和屬性的簡要說明。
1. shape
shape是XML文件的根節點,用來描述該形狀圖形是哪種幾何圖形。下面是shape節點的常用屬性說明。
- shape:字符串類型,圖形的形狀。形狀類型的取值說明見表2-10。
表2-10 形狀類型的取值說明

2. corners
corners是shape的下級節點,用來描述4個圓角的規格定義。若無corners節點,則表示沒有圓角。下面是corners節點的常用屬性說明。
- bottomLeftRadius:像素類型,左下圓角的半徑。
- bottomRightRadius:像素類型,右下圓角的半徑。
- topLeftRadius:像素類型,左上圓角的半徑。
- topRightRadius:像素類型,右上圓角的半徑。
- radius:像素類型,圓角半徑(若有上面4個圓角半徑的定義,則不需要radius定義)。
3. gradient
gradient是shape的下級節點,用來描述形狀內部的顏色漸變定義。若無gradient節點,則表示沒有漸變效果。下面是gradient節點的常用屬性說明。
- angle:整型,漸變的起始角度。為0時表示時鐘的9點位置,值增大表示往逆時針方向旋轉。例如,值為90表示6點位置,值為180表示3點位置,值為270表示0點/12點位置。
- type:字符串類型,漸變類型。漸變類型的取值說明見表2-11。
表2-11 漸變類型的取值說明

- centerX:浮點型,圓心的X坐標。當android:type="linear"時不可用。
- centerY:浮點型,圓心的Y坐標。當android:type="linear"時不可用。
- gradientRadius:整型,漸變的半徑。當android:type="radial"時才需要設置該屬性。
- centerColor:顏色類型,漸變的中間顏色。
- startColor:顏色類型,漸變的起始顏色。
- endColor:顏色類型,漸變的終止顏色。
- useLevel:布爾類型,設置為true無漸變色、false有漸變色。
4. padding
padding是shape的下級節點,用來描述形狀圖形與周圍視圖的間隔大小。若無padding節點,則表示四周不設間隔。下面是padding節點的常用屬性說明。
- bottom:像素類型,與下邊的間隔。
- left:像素類型,與左邊的間隔。
- right:像素類型,與右邊的間隔。
- top:像素類型,與上邊的間隔。
5. size
size是shape的下級節點,用來描述形狀圖形的尺寸大小(寬度和高度)。若無size節點,則表示寬高自適應。下面是size節點的常用屬性說明。
- height:像素類型,圖形高度。
- width:像素類型,圖形寬度。
6. solid
solid是shape的下級節點,用來描述形狀圖形內部的填充色彩。若無solid節點,則表示無填充顏色。下面是solid節點的常用屬性說明。
- color:顏色類型,內部填充的顏色。
7. stroke
stroke是shape的下級節點,用來描述形狀圖形四周邊線的規格定義。若無stroke節點,則表示不存在描邊。下面是stroke節點的常用屬性說明。
- color:顏色類型,描邊的顏色。
- dashGap:像素類型,每段虛線之間的間隔。
- dashWidth:像素類型,每段虛線的寬度。
- width:像素類型,描邊的厚度。若dashGap和dashWidth有一個值為0,則描邊為實線。
在實際開發中,常用的有3個節點:corners(圓角)、solid(填充)和stroke(描邊)。shape根節點的屬性一般不用設置(默認矩形就好了)。下面是一個shape圖形的XML描述文件代碼:

對應的形狀圖形效果界面如圖2-23所示。該形狀為一個圓角矩形,內部填充色為土黃色,邊緣線為灰色。

圖2-23 shape文件定義的圓角矩形效果
現在有個需求,客戶要求在界面上增加一個水平分割線,如果是你會怎么做呢?按照目前為止的學習成果有以下3個辦法。
(1)在TextView控件中連續填入許多橫線或下劃線。
(2)讓美工做一個橫線的切圖,然后將ImageView控件塞進橫線圖。
(3)使用剛學的shape,根節點的shape屬性設置為line表示直線圖形。
以上做法各有千秋,不過殺雞焉用牛刀,簡單的事情自然有簡單的辦法。最簡單的做法是在布局文件中增加一個View控件,高度設置為1dp、背景顏色設置為線條顏色,這樣便實現了水平分割線的需求。XML文件的示例代碼如下:

2.4.4 九宮格圖片
前面在介紹ImageView時專門舉了例子說明不同拉伸類型下的圖片顯示效果。當圖片被拉大時,畫面容易模糊,如果把圖片作為背景圖,模糊的情況會更嚴重。如圖2-24所示,一張按鈕圖片被拉得很寬,此時左右兩邊的邊緣線既變寬又變模糊了。

圖2-24 普通圖片與九宮格圖片的拉伸效果對比
為了解決這個問題,Android專門設計了點九圖片。點九圖片的擴展名是png,文件名后常帶有“.9”字樣。因為把一張圖片劃分成了3×3的九宮格區域,所以得名點九圖片,也叫九宮格圖片。如果背景是一個shape圖形,其stroke節點的width屬性已經設置了具體的像素值(如1dp),那么無論該shape圖形被拉伸到多大,描邊寬度始終都是1dp。點九圖片的實現原理與shape類似,即拉伸圖形時,只對內部進行拉伸,不對邊緣做拉伸操作。
為了演示九宮格圖片的展示效果,首先要制作幾張點九圖片。Android Studio現已集成了點九圖片的制作工具,首先找到待加工的原始圖片button_pressed_orig.png,右擊它彈出右鍵菜單如圖2-25所示。

圖2-25 點九圖片的制作菜單路徑
在右鍵菜單中選擇下面的“Create 9-Patch files”,并在隨后的對話框中單擊“OK”按鈕。接著drawable目錄就會出現一個名為“button_pressed_orig.9.png”的圖片文件,雙擊該文件,右側彈出點九圖片的加工窗口如圖2-26所示。

圖2-26 點九圖片的加工窗口界面
圖2-26的左側窗口是圖片加工區域,右側窗口是圖片預覽區域,從上到下依次是縱向拉伸預覽、橫向拉伸預覽、未拉伸預覽。在左側窗口圖片四周的馬賽克處單擊會出現一個黑點,把黑點左右或上下拖動會拖出一段黑線,不同方向上的黑線表示不同的效果。
如圖2-27所示,界面上邊的黑線指的是水平方向的拉伸區域。水平方向拉伸圖片時,只有黑線區域內的圖像會拉伸,黑線兩邊的圖像保持原狀,從而保證左右兩邊的邊框厚度不變。

圖2-27 點九圖片上邊的邊緣線
如圖2-28所示,界面左邊的黑線指的是垂直方向的拉伸區域。垂直方向拉伸圖片時,只有黑線區域內的圖像會拉伸,黑線兩邊的圖像保持原狀,從而保證上下兩邊的邊框厚度不變。

圖2-28 點九圖片左邊的邊緣線
如圖2-29所示,界面下邊的黑線指的是該圖片作為控件背景時,控件內部的文字左右邊界只能放在黑線區域內。這里Horizontal Padding的效果就相當于android:paddingLeft與android:paddingRight。

圖2-29 點九圖片下邊的邊緣線
如圖2-30所示,界面右邊的黑線指的是該圖片作為控件背景時,控件內部的文字上下邊界只能放在黑線區域內。這里Vertical Padding的效果就相當于android:paddingTop與android:paddingBottom。

圖2-30 點九圖片右邊的邊緣線
在實際開發中,前兩個屬性使用的比較多,因為很多場景都要求拉伸圖片時要保真。后兩個屬性一般用得不多,但若不知道,遇到問題還挺麻煩的。筆者以前做開發時看到某個頁面的文字總是與頂端有段間隔,可是無論怎么調整XML和代碼都沒法縮小間隔,后來才想起來檢查該頁面的背景圖片,結果打開之后發現該圖片是點九圖片,原來在水平和垂直方向都設置了padding,這才解決了一大困惑。