前幾天,面試的時候,有問道關於如何自適應不一樣分辨率屏幕的問題。當時也是隻知其一;不知其二,今天索性看了不少資料,好好的總結了下。java
首先解釋幾個基本的概念:android
in:表示英寸,是屏幕的物理尺寸。每英寸等於2.54釐米。例如,形容手機屏幕大小,常常說,3.2(英)寸、3.5(英)寸、4(英)寸就是指這個單位。這些尺寸是屏幕的對角線長度。若是手機的屏幕是3.2英寸,表示手機的屏幕(可視區域)對角線長度是3.2*2.54 = 8.128釐米。web
px:表示屏幕實際的象素。例如,320*480的屏幕在橫向有320個象素,在縱向有480個象素。面試
dip或dp(與密度無關的像素):這個和設備硬件有關,爲了支持WVGA、HVGA和QVGA推薦使用這個。一種基於屏幕密度的抽象單位。設置一些view的寬高能夠用這個,通常狀況下,在不一樣分辨率,都不會有縮放的感受。若是用px的話,320px佔滿HVGA的寬度,到WVGA上就只能佔一半不到的屏幕了,那必定不是你想要的。app
sp: 除了與密度無關外,還與scale無關 主要處理字體的大小。 ide
density:屏幕密度,每英寸有多少個像素顯示點,與分辨率是兩個概念oop
VGA:480*640佈局
Low:120 Medium:240 High:480測試
方便記憶的法子:QVGA即"Quarter VGA"。顧名思義即VGA的四分之一尺寸字體
HVGA 即「Half VGA」
WVGA即VGA的另外一種形式,比VGA分辨率高,別名 : Wide VGA, ,其分辯率爲800×480象素。是擴大了VGA(640×480)的分辨率。應用於PDA和手機等,由於不少網頁的寬度都是800,因此WVGA的屏幕會更加適和於瀏覽網頁,能夠說是將來手持設備的分辨率的大趨勢
換算公式:px=(density/160)dp其中density通常爲3個經常使用固定值240/160/120
好比若是在屏幕爲320*480設置一個view的大小爲320px,則這個view充滿整個width,若是設備屏幕爲480*800,則這個view只是充滿width的320/480=2/3。顯然不符合自適應不一樣的分辨率要求。若是設置view的大小爲320dp,則根據px = (density/160)dp,480*800的屏幕密度爲240,可知px=1.5dp。因此真實像素大小爲320*1.5=480
而後我在模擬器上測試了下,但發現一個問題,打印出來的並不是是模擬器的真實分辨率,又查了下,成功解決
在一個Activity的onCreate方法中,寫入以下代碼:
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 屏幕寬度(像素)
int height = metric.heightPixels; // 屏幕高度(像素)
float density = metric.density; // 屏幕密度(0.75 / 1.0 / 1.5)
int densityDpi = metric.densityDpi; // 屏幕密度DPI(120 / 160 / 240)
可是,須要注意的是,在一個低密度的小屏手機上,僅靠上面的代碼是不能獲取正確的尺寸的。好比說,一部240x320像素的低密度手機,若是運行上述代碼,獲取到的屏幕尺寸是320x427。所以,研究以後發現,若沒有設定多分辨率支持的話,Android系統會將240x320的低密度(120)尺寸轉換爲中等密度(160)對應的尺寸,這樣的話就大大影響了程序的編碼。因此,須要在工程的AndroidManifest.xml文件中,<manifest>中加入supports-screens節點,具體的內容以下:
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:resizeable="true"
android:anyDensity="true" />
這樣的話,當前的Android程序就支持了多種分辨率,那麼就能夠獲得正確的物理尺寸了。
如此測試經過沒問題!
另外一方面:默認狀況下面系統會自動調整和縮放位圖,可是不免拉伸位圖
apk的資源包中,當屏幕density=240時使用hdpi標籤的資源
當屏幕density=160時,使用mdpi標籤的資源
當屏幕density=120時,使用ldpi標籤的資源。
不加任何標籤的資源是各類分辨率狀況下共用的
1在XML佈局,使用wrap_content和fill_parent來填充整個父窗口;
2使用FrameLayout的,而不是AbsoluteLayout,減小界面佈局對屏幕大小的依賴;
3 NEVER usehard-coding for pixel value, use dip (density independent pixel)(不要硬編碼像素值px,而是使用獨立像素值的dip)
4根據density和resolution 爲不一樣的設備準備合適的圖片資源。
具體方案:
1.根據不一樣屏幕尺寸,提供不一樣佈局
爲了保證你的位圖是最好看的,默認狀況下面,android會自動調整應用程序的佈局,可是大多數狀況下面,根據廣義尺寸,小,正常,大,更大去增長不一樣的佈局資源。好比,若是須要對大小爲large的屏幕提供支持,須要在res目錄下新建一個文件夾layout-large/並提供layout。固然,也能夠在res目錄下創建layout-port和layout-land兩個目錄,裏面分別放置豎屏和橫屏兩種佈局文件,以適應對橫屏豎屏自動切換。
2.提供不一樣的屏幕密度和不一樣的位圖drawables
根據廣義密度,低,中型, 高,特高去添加不一樣的位圖資源。好比,如需對密度爲low的屏幕提供合適的圖片,需新建文件夾drawable-ldpi/。應儘可能使用點9格式的圖片,圖片大小的肯定:low:medium:high:extra high比例爲3:4:6:8。舉例來講,對於中等密度(medium)的屏幕你的圖片像素大小爲48×48,那麼低密度(low)屏幕的圖片大小應爲36×36,高(high)的爲72×72,extra high爲96×96。
3關於系統怎麼動態的尋找替代資源?
1.系統根據當前的屏幕大小和密度,而後動態的採用程序中提供特定的資源。
2.若是沒有匹配的資源,系統會使用默認的資源進行縮放從而符合當前屏幕的資源,「默認」的資源是那些沒有標籤配置限定符。
關於系統的資源配置的目錄(Android系統支持多配置資源文件,咱們能夠追加新的資源目錄到你的Android項目中。命名規範:資源名字-限制符
最後:
在xml佈局文件中,咱們既能夠設置px,也能夠設置dp(或者dip)。通常狀況下,咱們都會選擇使用dp,這樣能夠保證不一樣屏幕分辨率的機器上佈局一致。可是在代碼中,如何處理呢?不少控件的方法中都只提供了設置px的方法,例如setPadding,並無提供設置dp的方法。這個時候,若是須要設置dp的話,就要將dp轉換成px了。
如下是一個應用類,方便進行px和dp之間的轉換。