遇到一個問題,個人地圖浮標圖片在WVGA手機上正好,在QVGA上就顯的太大,因此我要根據屏幕的不一樣調整浮標的大小使其在QVGA大小合適。有的同事提出了依據分辨率來區分不一樣的屏幕,可是單WVGA就支持好幾種不一樣的分辨率,QVGA又支持好幾種。。。並且更神奇的時候,有時候,經過代碼獲取屏幕分辨率居然獲得了 320 x 427 ,Android文檔是不支持這種分辨率的,因此依據分辨率來區分不一樣的屏幕是行不通的。android
還好經過仔細研讀文檔,「各類VGA的density是不一樣的,(hdpi: 240 , ldpi: 120 , mdpi: 160 , xhdpi: 320)」,因此只要求出不一樣屏幕的density,就能夠知道該手機屬於的屏幕類型。程序員
首先是幾個基本概念:web
1.屏幕尺寸Screen size佈局
即顯示屏幕的實際大小,按照屏幕的對角線進行測量。編碼
爲簡單起見,Android把全部的屏幕大小分爲四種尺寸:小,普通,大,超大(分別對應:small, normal, large, and extra large).spa
應用程序能夠爲這四種尺寸分別提供不一樣的自定義屏幕布局-平臺將根據屏幕實際尺寸選擇對應佈局進行渲染,這種選擇對於程序側是透明的。3d
2.屏幕長寬比Aspect ratioorm
長寬比是屏幕的物理寬度與物理高度的比例關係。應用程序能夠經過使用限定的資源來爲指定的長寬比提供屏幕布局資源。xml
3.屏幕分辨率Resolution圖片
在屏幕上顯示的物理像素總和。須要注意的是:儘管分辨率一般用寬x高表示,但分辨率並不意味着具體的屏幕長寬比。
在Andorid系統中,應用程序不直接使用分辨率。
4.密度Density
根據像素分辨率,在屏幕指定物理寬高範圍內能顯示的像素數量。
在一樣的寬高區域,低密度的顯示屏能顯示的像素較少,而高密度的顯示屏則能顯示更多的像素。
屏幕密度很是重要,由於其它條件不變的狀況下,一共寬高固定的UI組件(好比一個按鈕)在在低密度的顯示屏上顯得很大, 而在高密度顯示屏上看起來就很小。
爲簡單起見,Android把全部的屏幕分辨率也分爲四種尺寸:小,普通,大,超大(分別對應:small, normal, large, and extra large).
應用程序能夠爲這四種尺寸分別提供不一樣的資源-平臺將透明的對資源進行縮放以適配指定的屏幕分辨率。
密度無關的像素( DIP )
指一個抽象意義上的像素,程序用它來定義界面元素。它做爲一個與實際密度無關的單位,幫助程序員構建一個佈局方案(界面元素的寬度,高度,位置)。
一個與密度無關的像素,在邏輯尺寸上,與一個位於像素密度爲 160DPI的屏幕上的像素是一致的,這也是Android平臺所假定的默認顯示設備。在運行的時候,平臺會以目標屏幕的密度做爲基準,「透明地」處理所 有須要的DIP縮放操做。要把密度無關像素轉換爲屏幕像素,能夠用這樣一個簡單的公式: pixels = dips * (density / 160)。舉個例子,在 DPI爲 240的屏幕上, 1個 DIP等於 1.5個物理像素。咱們強烈推薦你用 DIP來定義你程序的界面佈局,由於這樣能夠保證你的 UI在各類分辨率的屏幕上均可以正常顯示
在一個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文件中,加入supports-screens節點,具體的內容以下:
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:resizeable="true"
android:anyDensity="true"/>
這樣的話,當前的Android程序就支持了多種分辨率,那麼就能夠獲得正確的物理尺寸了。
// 獲取屏幕密度(方法1)
int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕寬(像素,如:480px)
int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); // 屏幕高(像素,如:800p)
Log.e(TAG + " getDefaultDisplay", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);
// 獲取屏幕密度(方法2)
DisplayMetrics dm = new DisplayMetrics();
dm = getResources().getDisplayMetrics();
float density = dm.density; // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)
int densityDPI = dm.densityDpi; // 屏幕密度(每寸像素:120/160/240/320)
float xdpi = dm.xdpi;
float ydpi = dm.ydpi;
Log.e(TAG + " DisplayMetrics", "xdpi=" + xdpi + "; ydpi=" + ydpi);
Log.e(TAG + " DisplayMetrics", "density=" + density + "; densityDPI=" + densityDPI);
screenWidth = dm.widthPixels; // 屏幕寬(像素,如:480px)
screenHeight = dm.heightPixels; // 屏幕高(像素,如:800px)
Log.e(TAG + " DisplayMetrics(111)", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);
// 獲取屏幕密度(方法3)
dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
density = dm.density; // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)
densityDPI = dm.densityDpi; // 屏幕密度(每寸像素:120/160/240/320)
xdpi = dm.xdpi;
ydpi = dm.ydpi;
Log.e(TAG + " DisplayMetrics", "xdpi=" + xdpi + "; ydpi=" + ydpi);
Log.e(TAG + " DisplayMetrics", "density=" + density + "; densityDPI=" + densityDPI);
int screenWidthDip = dm.widthPixels; // 屏幕寬(dip,如:320dip)
int screenHeightDip = dm.heightPixels; // 屏幕寬(dip,如:533dip)
Log.e(TAG + " DisplayMetrics(222)", "screenWidthDip=" + screenWidthDip + "; screenHeightDip=" + screenHeightDip);
screenWidth = (int)(dm.widthPixels * density + 0.5f); // 屏幕寬(px,如:480px)
screenHeight = (int)(dm.heightPixels * density + 0.5f); // 屏幕高(px,如:800px)
Log.e(TAG + " DisplayMetrics(222)", "screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);