1. 概述
在平時(shí)工作的過程中魄藕,總是會(huì)遇到這樣的問題颤专,將一張圖片放到drawable、drawable-ldpi逮光、drawable-mdpi代箭、drawable-hdpi墩划、drawable-xhdpi、drawable-xxhdpi或者drawable-xxxhdpi目錄中嗡综,在app運(yùn)行時(shí)乙帮,加載到內(nèi)存中的圖片與資源目錄中的圖片相比尺寸可能被縮小或者放大,本篇文章就是來解析這個(gè)問題的原因蛤高。
2. 預(yù)備知識(shí)
2.1 術(shù)語和概念
Screen size(屏幕尺寸):按屏幕對(duì)角測量的實(shí)際物理尺寸蚣旱。
為簡便起見,Android 將所有實(shí)際屏幕尺寸分組為四種通用尺寸:small, normal, large, and extra-large戴陡。
Screen density(屏幕密度):屏幕物理區(qū)域中的像素量塞绿;通常稱為dpi(dots per inch)。例如恤批, 與“ normal”或“ high”密度屏幕相比异吻,“ low”密度屏幕在給定物理區(qū)域的像素較少。
為簡便起見喜庞,Android 將所有屏幕密度分組為六種通用密度: low, medium, high, extra-high, extra-extra-high, and extra-extra-extra-high诀浪。
Orientation(方向):從用戶的角度來看屏幕的方向,即橫屏還是豎屏延都。 請(qǐng)注意雷猪,默認(rèn)情況下不僅不同的設(shè)備以不同的方向運(yùn)行,而且當(dāng)用戶旋轉(zhuǎn)設(shè)備時(shí)晰房,方向可能會(huì)在運(yùn)行時(shí)發(fā)生變化求摇。
Resolution(分辨率):屏幕上物理像素的總數(shù)。添加對(duì)多種屏幕的支持時(shí)殊者, 應(yīng)用不會(huì)直接使用分辨率与境;而只應(yīng)關(guān)注通用尺寸和密度組指定的屏幕尺寸及密度。
Density-independent pixel(密度無關(guān)像素 dp):在定義UI布局時(shí)應(yīng)使用的虛擬像素單位猖吴,用于以密度無關(guān)的方式表示布局尺寸或位置摔刁。
一個(gè)密度無關(guān)像素等于 160 dpi 屏幕上的一個(gè)物理像素,“ medium”的屏幕密度為160 dpi海蔽。在運(yùn)行時(shí)共屈,系統(tǒng)會(huì)根據(jù)當(dāng)前屏幕的實(shí)際密度按需要對(duì)資源進(jìn)行適當(dāng)?shù)目s放 。dp單位轉(zhuǎn)換為屏幕像素很簡單: px = dp * (dpi / 160)党窜,例如拗引,在 240 dpi 屏幕上,1dp等于 1.5 物理像素刑然。在定義應(yīng)用UI時(shí)應(yīng)始終使用 dp 單位 ,以確保在不同密度的屏幕上顯示UI的大小一致暇务。
2.2 屏幕尺寸和屏幕密度的分類
從 Android 1.6(API 級(jí)別 4)開始泼掠,Android 支持多種屏幕尺寸和密度怔软,反映設(shè)備可能具有的多種不同屏幕配置。 您可以通過Android系統(tǒng)的功能優(yōu)化應(yīng)用在各種屏幕配置下的用戶界面 择镇,確保應(yīng)用不僅正常渲染挡逼,而且在每個(gè)屏幕上提供最佳的用戶體驗(yàn)。
為簡化為多種屏幕設(shè)計(jì)用戶界面的方式腻豌,Android 將實(shí)際屏幕尺寸和密度的范圍分為:
1> 四種通用尺寸:small, normal, large, and xlarge
注意:從 Android 3.2(API 級(jí)別 13)開始家坎,這些尺寸組已棄用,而采用根據(jù)可用屏幕寬度管理屏幕尺寸的新技術(shù)吝梅。如果為 Android 3.2 和更高版本開發(fā)虱疏,請(qǐng)參閱聲明適用于 Android 3.2 的平板電腦布局以了解更多信息。
2> 六種通用的密度:
ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi
通用的尺寸和密度按照基線配置(即normal尺寸和 mdpi密度)排列苏携。 此基線基于第一代 Android 設(shè)備 (T-Mobile G1) 的屏幕配置做瞪,該設(shè)備采用 HVGA 屏幕(在 Android 1.6 之前,這是 Android 支持的唯一屏幕配置)右冻。
每種通用的尺寸和密度都涵蓋一個(gè)實(shí)際屏幕尺寸和密度范圍装蓬。例如, 兩部都報(bào)告normal屏幕尺寸的設(shè)備在手動(dòng)測量時(shí)纱扭,實(shí)際屏幕尺寸和高寬比可能略有不同牍帚。類似地,對(duì)于兩臺(tái)報(bào)告 hdpi 屏幕密度的設(shè)備乳蛾,其實(shí)際像素密度可能略有不同暗赶。 Android 將這些差異抽象概括到應(yīng)用,使您可以只提供為通用尺寸和密度設(shè)計(jì)的UI屡久,讓系統(tǒng)按需要做最終調(diào)整(具體怎么調(diào)整下面第3部分會(huì)具體說明)忆首。 下圖說明不同的尺寸和密度如何粗略歸類為不同的尺寸 和密度組。
在為不同的屏幕尺寸設(shè)計(jì)UI時(shí)被环,您會(huì)發(fā)現(xiàn)每種設(shè)計(jì)都需要最小空間糙及。因此,上述每種通用的屏幕尺寸都關(guān)聯(lián)了系統(tǒng)定義的最低分辨率筛欢。這些最小尺寸以“dp”單位表示 — 在定義布局時(shí)應(yīng)使用相同的單位 — 這樣系統(tǒng)無需擔(dān)心屏幕密度的變化浸锨。
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp
要針對(duì)不同的屏幕尺寸和密度優(yōu)化應(yīng)用的 UI,可為任何通用的尺寸和密度提供備用資源版姑。 通常柱搜,應(yīng)為不同的屏幕尺寸提供備選布局,為不同的屏幕密度提供備選位圖圖像剥险。 在運(yùn)行時(shí)聪蘸,系統(tǒng)會(huì)根據(jù)當(dāng)前設(shè)備屏幕的通用尺寸或密度匹配適當(dāng)?shù)馁Y源。
2.3 Density independence
應(yīng)用顯示在密度不同的屏幕上時(shí),如果保持用戶界面元素的物理尺寸(從用戶的視角)一致健爬,也就實(shí)現(xiàn)了“Density independence” 控乾。
保持Density independence很重要,因?yàn)槿绻麤]有此功能娜遵,UI 元素(例如 按鈕)在低密度屏幕上看起來較大蜕衡,在高密度屏幕上看起來較小。這些密度相關(guān)的大小變化可能給應(yīng)用布局和易用性帶來問題设拟。下面兩張圖依次顯示了應(yīng)用不提供Density independence和提供Density independence時(shí)的差異慨仿。
在圖 2 中躲雅,文本視圖和位圖可繪制對(duì)象具有以像素(px單位)指定的尺寸鼎姊,因此視圖的物理尺寸在低密度屏幕上更大,在高密度屏幕上更小相赁。這是因?yàn)橄嗫埽m然實(shí)際屏幕尺寸可能相同,但高密度屏幕的每英寸像素更多(同樣多的像素在一個(gè)更小的區(qū)域內(nèi))钮科。在圖 3 中唤衫,布局尺寸以密度獨(dú)立的像素(dp 單位)指定。由于密度獨(dú)立像素的基線是medium密度屏幕绵脯,因此具有medium密度屏幕的設(shè)備看起來與圖 2 一樣佳励,對(duì)于low密度(1dp = 0.75px)和high密度(1dp = 1.5px)的屏幕,文本視圖和位圖可繪制對(duì)象的大小與medium密度屏幕相同蛆挫。
大多數(shù)情況下赃承,確保應(yīng)用中的density independence很簡單,只需以適當(dāng)?shù)拿芏泉?dú)立像素(dp 單位)或 "wrap_content" 指定所有布局尺寸值悴侵。
3. 基于屏幕密度的圖片縮放規(guī)則
3.1 匹配規(guī)則
假設(shè)當(dāng)前屏幕密度對(duì)應(yīng)的通用分類為xhdpi瞧剖,系統(tǒng)會(huì)優(yōu)先在drawable-xhdpi目錄中尋找需要的drawable資源,如果沒有找到可免,就會(huì)依次在drawable-xxhdpi抓于、drawable-xxxhdpi目錄中尋找需要的drawable資源,如果還是沒有找到浇借,就會(huì)到drawable-nodpi中尋找需要的drawable資源捉撮,如果還是沒有找到,就會(huì)依次在drawable-hdpi妇垢、drawable-mdpi巾遭、drawable肉康、drawable-ldpi目錄中尋找需要的drawable資源,如果還是沒有找到灼舍,那是不可能的迎罗,因?yàn)檫@樣的話編譯都不會(huì)過的。
3.2 縮放規(guī)則
1> 按照上面的方式找到匹配的drawable資源后片仿,假設(shè)當(dāng)前屏幕密度為x,匹配的drawable資源所在的目錄的屏幕密度為y尤辱,那就會(huì)按照 x/y 比例縮放匹配的drawable資源砂豌,以匹配當(dāng)前的屏幕密度。
2> 對(duì)于放在有nodpi配置限定符的drawable資源目錄中光督。例如:res/drawable-nodpi/icon.png阳距,當(dāng)系統(tǒng)使用此文件夾中的 icon.png 位圖時(shí),不會(huì)根據(jù)當(dāng)前屏幕密度縮放结借。
3.3 舉例驗(yàn)證:
1> 通過斷點(diǎn)的方式獲取到手機(jī)屏幕密度筐摘,如下圖所示:
我的手機(jī)的屏幕密度為420dpi衅斩,對(duì)應(yīng)屏幕密度通用分類中的xxhdpi(480dpi)拇砰。
2> 驗(yàn)證3.1 匹配規(guī)則
通過在drawable、drawable-ldpi雏门、drawable-mdpi柳畔、drawable-hdpi馍管、drawable-xhdpi、drawable-xxhdpi薪韩、drawable-xxxhdpi和drawable-nodpi目錄中各放一張名稱相同內(nèi)容不同的圖片确沸,可以很容易驗(yàn)證3.1 中的規(guī)則,有興趣的同學(xué)可以自己驗(yàn)證一下俘陷。
3> 驗(yàn)證3.2 縮放規(guī)則
僅在drawable-xxhdpi目錄下放置一張圖片罗捎,圖片大小如下圖所示:
在不進(jìn)行縮放的情況下加載到內(nèi)存中,內(nèi)存中該圖片的大小應(yīng)該是:
507*760*4 = 1541280 byte
接著將這個(gè)圖片放到imageview中拉盾,通過斷點(diǎn)的方式看一下該圖片被加載到內(nèi)存中的實(shí)際大薪安恕:
可以看到圖片的大小被壓縮了,根據(jù)3.2中的規(guī)則計(jì)算一下縮小的過程:
縮放后的寬為:(420/480)*507 = 444
縮放后的高為:(420/480)*760 = 665
縮放后的大小為:444*665*4 = 1181040 byte盾剩,和上面截圖中的大小相同雷激。
下面僅在drawable-hdpi目錄下放置一張圖片,圖片大小如下圖所示:
在不進(jìn)行縮放的情況下加載到內(nèi)存中告私,內(nèi)存中該圖片的大小應(yīng)該是:
700*1049*4 = 2937200 byte
接著將這個(gè)圖片放到imageview中屎暇,通過斷點(diǎn)的方式看一下該圖片被加載到內(nèi)存中的實(shí)際大小:
可以看到圖片的大小被放大了驻粟,根據(jù)3.2中的規(guī)則計(jì)算一下放大的過程:
放大后的寬為:(420/240)*700 = 1225
放大后的高為:(420/240)*1049 = 1836
放大后的大小為:1225*1836*4 = 8996400 byte根悼,和上面截圖中的大小相同凶异。
下面僅在drawable目錄下放置一張圖片,圖片大小如下圖所示:
在不進(jìn)行縮放的情況下加載到內(nèi)存中挤巡,內(nèi)存中該圖片的大小應(yīng)該是:
800*577*4 = 1846400 byte
接著將這個(gè)圖片放到imageview中剩彬,通過斷點(diǎn)的方式看一下該圖片被加載到內(nèi)存中的實(shí)際大小:
由于系統(tǒng)假設(shè)默認(rèn)資源( 沒有配置限定符目錄中的資源)針對(duì)基線屏幕密度 (mdpi) 而設(shè)計(jì)矿卑,因此drawable目錄對(duì)應(yīng)的屏幕密度是160dpi喉恋。
可以看到圖片的大小被放大了,根據(jù)3.2中的規(guī)則計(jì)算一下放大的過程:
放大后的寬為:(420/160)*800 = 2100
放大后的高為:(420/160)*577 = 1515
放大后的大小為:2100* 1515*4 = 12726000 byte母廷,和上面截圖中的大小相同轻黑。
下面僅在drawable-nodpi目錄下放置一張圖片,圖片大小如下圖所示:
在不進(jìn)行縮放的情況下加載到內(nèi)存中琴昆,內(nèi)存中該圖片的大小應(yīng)該是:
600*900*4 = 2160000 byte
接著將這個(gè)圖片放到imageview中氓鄙,通過斷點(diǎn)的方式看一下該圖片被加載到內(nèi)存中的實(shí)際大小:
可以看到該圖片的大小沒有發(fā)生改變业舍。