4.0后,新建android工程,會自動生成drawable,drawalbe-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi,drawable-xxhdpi六個文件夾,除drawable外,其他5個文件夾對應四種級別的density:120dip(low),160dip(medium),240dip(high),320dip(xhigh),480dip(drawable-xxhdpi)。目前主流做法都是把圖片文件放在drawable-hdpi文件夾內,和圖片相關的xml文件(如按鈕xml,用以在按鈕點擊時顯示不同的背景圖片效果)放在drawable文件夾內。
所謂density,是指屏幕上的像素密度,以160dip為標准密度。舉例來說,當我們在布局文件layout.xml中放置一個View
<View android:layout_height="1dip" android:layout_width="100dip"/>
該View在密度為160dip的屏幕上顯示的長度為100px(像素)長,而在320dip的屏幕上它的長度將為200px。
而當圖片處於drawable文件夾內時,也需要做這種轉換。假如在drawable-mdpi的文件夾內有一張22*44的圖片,通過程序將其讀入系統中時,假設屏幕密度為320dip,那它在內存中的大小將是44*88。
前面說過,目前主流做法是將圖片放置在drawable-hdpi文件夾內,該文件夾對應的density是240dip,但其實現在的手機一般都是320dip甚至480dip了,所以放置在hdpi文件夾內的圖片在顯示時都是已經自動拉伸過了。
還有個問題,當直接讀取sd卡或assert文件夾內的圖片時,圖片的大小是怎么樣的呢?當我們讀取sd卡內的圖片時,我們首先獲取的不是drawbale對象而是個bitmap對象,該bitmap對象的width和height對應的是圖片的真實像素大小。而將bitmap對象轉換為drawable時,除非我們手動設置了目標density,否則不進行縮放。
BitmapDrawable bmpDrawable = new BitmapDrawable(bitmap);
使用這個構造函數,默認的density是160,該構造函數已經被摒棄了,推薦使用下一個
BitmapDrawable bmpDrawable = new BitmapDrawable(getResources(),bitmap);
該構造函數會通過getResources獲取到手機的density,將其設置為默認的density。
getResources().getDisplayMetrics().densityDpi
若我們需要進行縮放,可以通過下述方法設置目標density。
bmpDrawable.setTargetDensity(160)
在320dip長度的屏幕上,該bmpDrawable將會縮小為一半。
注:我原先以為 new BitmapDrawable(getResources(),bitmap)這個構造函數是為了將圖片根據當前屏幕密度進行縮放。如屏幕密度為320dip時,在用了該構造函數后圖片會自動放大1倍(Bitmap對象默認的density是160),但認真看了源碼后發現,該方式是為了修改默認的density,即將160改為了320,之后再通過setTargetDensity方法設置真正需要縮放的密度。關於這點我實在想不到它的應用場景,感覺很不合理。