標籤:android 資源
1. 圖片縮放後對齊的問題
在Android的開發中,如何使用圖片對很多開發人員是一個很頭痛的事。最常見的問題是在一台手機上調試好的UI,在不同dpi的手機上會變形。
Android提供了適配不同dpi的方案,每種dpi都有對應的資來源目錄。但是我們在開發程式時,對圖片資源卻不能這樣處理,因為圖片資源太大,如果我們每種類型的dpi都使用一套圖片,應用的尺寸就會急劇膨脹,這可不是我們想看到的結果。
如果只有一套圖片,但是有drawable,drawable-mdpi,drawable-hdpi等好幾個目錄,到底放在哪個目錄下才能保證在每種dpi的裝置上都顯示正確了?這個問題無法給出一個簡單的答案,只能是根據具體情況分析。
首先,我們要理解圖片放在這些目錄下會有什麼樣的後果:
q drawable目錄:這個是所謂的“預設”目錄。如果把圖片放在這裡,從最終效果上講,和放在drawable-mdpi目錄下是一樣的。
q drawable-nodpi目錄:放在這個目錄下的圖片被裝載進記憶體後,不會被縮放,所謂不縮放的意思是一張72x72像素的圖片,在記憶體中的大小仍然是72x72像素。但是在不同的裝置上這張圖片看起來大小會不一樣。
q drawable-mdpi,drawable-xdpi,dreawable-xhdpi:如果將圖片放在這些和dpi相關的目錄下,當程式運行在相同dpi的裝置上時,不會被縮放;當運行在dpi不相同的裝置上時,會根據dpi之間的換算關係進行縮放。
對於放在drawable-nodpi下的圖片比較簡單,不用太多解釋。但是對於放在其他目錄下的圖片,Android對圖片縮放的目的是什麼呢?其實目的和在layout檔案中使用dp做為數量單位一樣,是為了讓一張圖片在不同dpi的裝置上看起來大小一樣。例如,一張放在drawable-mdpi目錄下,大小為72x72像素的圖片,如果運行在mdpi的裝置上,大小還是72x72像素,但是運行在drawable-hdpi的裝置上時,尺寸就會被放大為108x108像素。
如果不考慮圖片縮放的效果,通過縮放能夠讓應用適應不同的螢幕,不是很好嗎?為什麼開發人員還會覺得頭痛呢?這是因為在開發中,很多UI效果是通過拼圖的方式實現的,如果兩張圖片縮放後無法對齊,哪怕只有一個像素,也會讓效果失色。要解決這個問題,先讓我們看看Android是如何進行縮放的。
Android上最常見的四種dpi是ldpi(120dpi),mdpi(160dpi),hdpi(240dpi)和xhdpi(320dpi)。這四種dpi的比值是120:160:240:320,化簡後就是3:4:6:8。放在mdpi目錄下的檔案,在不同dpi的裝置上縮放後的大小就是n*3/4,n*4/4,n*6/4和n*8/4(n為圖片大小),如果希望放在mdpi下的圖片縮放的效果最好,圖片的尺寸必須是4的倍數,否則演算法在處理圖片的過程中,會不按比例的加入或刪除幾行(或幾列)的像素,這樣兩張圖片中的線條在縮放後就可能會相互錯開幾個像素。同理,放在ldpi下的圖片,大小最好是3的倍數;放在hdpi下的圖片,大小最好是6的倍數;放在xhdpi下的圖片,大小最好是8的倍數。當然我們並不是要求每一張圖都要符合這個規律,但是對於哪些需要精確對齊的圖片,這樣做還是有必要的。所以一套圖片放在哪個目錄下不是關鍵,關鍵是要確定圖片的大小。
注意,這裡談論的圖片縮放問題是指在圖片裝載進記憶體時就會進行的縮放。除此以外,很多widget在使用圖片時還會再次縮放。當然Android也提供了方法禁止widget縮放。例如最常用的ImageView類可以通過設定scaleType屬性為“center”來禁止縮放,或者把ImageView的寬度和高度設為“wrap_content”。但是要明白的是,這裡設定了讓ImageView不去縮放圖片,圖片裝載時還是會被系統縮放的,很多開發人員在這裡迷惑了,以為設定了Widget禁止縮放後,顯示效果會和原圖一樣,折騰很長時間也不知道問題出在哪。
如果正在使用的widget也會去縮放圖片,同樣也要注意縮放的大小問題,原則也是要讓每種圖片按相同整數倍進行縮放。還要注意的是,在很多情況下,我們在布局上會讓UI的寬度撐滿整個螢幕。但是很多相同dpi,差不多大小的裝置,它們的螢幕解析度也可能有細微差別,這樣如果根據螢幕寬度來縮放,可能有的裝置看上去很完美,有的裝置卻還是對不齊。這種情況下,如果希望達到最佳效果,只能是根據dpi還有螢幕的寬度來動態計算出一個最佳的寬度了,既要儘可能的佔滿螢幕,又要讓縮放符合比例。但是這樣就太麻煩了,而且也未必在所有的情況下都能有這麼一個完美值。最好的辦法還是在明白問題所在後,從UI設計上就要避免這種問題的出現。所以類似的問題沒有一勞永逸的解決方案,需要我們根據實際情況來調整。
2. NinePatch圖片的縮放
NinePatch圖片是Android中定義的一種特殊的圖片格式,它通過在普通圖片的邊緣做標記的方式把一張圖片分成9個部分。如下所示:
對NinePatch圖縮放時,圖片中1,3,7,9四個角保持不變。2號和8號地區水平縮放,4號和6號地區垂直縮放,5號地區則全縮放。
但是對NinePath圖片最大的誤解就是NinePatch的四個角是絕對不縮放的。除非圖片是放在目錄drawable-nodpi下,或者是運行在相同dpi的裝置上,NinePath圖片裝載進記憶體時一樣會先根據dpi的比值進行縮放。所謂四個角不縮放,是指裝載進記憶體後,再調用縮放函數進行縮放時,四個角的尺寸不會再變化了。所以我們在製作圓角的NinePathc圖時要注意,指定的四個角的大小也要符合前面講的規律,根據所放目錄的dpi來決定四個角的像素大小。
3. 為圖片指定Density
Android裝載圖片時會根據當前裝置的dpi進行縮放。我們也能在Bitmap類裡或BitmapDrawable類裡調用setDensity()和setTargetDesnsity()來改變一張圖片的縮放比例。
publicfinal class Bitmap implements Parcelable {
public void setDensity(intdensity);
......
}
publicclass BitmapDrawable extends Drawable {
public void setTargetDensity(intdensity);
......
}
當調用這兩個方法後,圖片將不按照預設的density來縮放,而是根據我們指定的density。
Android圖片資源的縮放問題