獲取設備的屏幕尺寸與密度的方法

Android 獲取屏幕尺寸與密度

    遇到一個問題,我的地圖浮標圖片在WVGA手機上正好,在QVGA上就顯的太大,所以我要根據屏幕的不同調整浮標的大小使其在QVGA大小合適。有的同事提出了依據分辨率來區分不同的屏幕,但是單WVGA就支持好幾種不同的分辨率,QVGA又支持好幾種。。。而且更神奇的時候,有時候,通過代碼獲取屏幕分辨率竟然得到了 320 x 427 ,Android文檔是不支持這種分辨率的,所以依據分辨率來區分不同的屏幕是行不通的。

    還好通過仔細研讀文檔,“各種VGA的density是不同的,(hdpi: 240 , ldpi: 120 , mdpi: 160 , xhdpi: 320)”,所以只要求出不同屏幕的density,就可以知道該手機屬於的屏幕類型。
 

首先是幾個基本概念:

1.屏幕尺寸Screen size

即顯示屏幕的實際大小,按照屏幕的對角線進行測量。

爲簡單起見,Android把所有的屏幕大小分爲四種尺寸:小,普通,大,超大(分別對應:small, normal, large, and extra large).

應用程序可以爲這四種尺寸分別提供不同的自定義屏幕布局-平臺將根據屏幕實際尺寸選擇對應佈局進行渲染,這種選擇對於程序側是透明的。

2.屏幕長寬比Aspect ratio

長寬比是屏幕的物理寬度與物理高度的比例關係。應用程序可以通過使用限定的資源來爲指定的長寬比提供屏幕布局資源。

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. // 獲取屏幕密度(方法1)  
  2. int screenWidth  = getWindowManager().getDefaultDisplay().getWidth();       // 屏幕寬(像素,如:480px)  
  3. int screenHeight = getWindowManager().getDefaultDisplay().getHeight();      // 屏幕高(像素,如:800p)  
  4.   
  5. Log.e(TAG + "  getDefaultDisplay""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  
  6.   
  7.   
  8. // 獲取屏幕密度(方法2)  
  9. DisplayMetrics dm = new DisplayMetrics();  
  10. dm = getResources().getDisplayMetrics();  
  11.   
  12. float density  = dm.density;        // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)  
  13. int densityDPI = dm.densityDpi;     // 屏幕密度(每寸像素:120/160/240/320)  
  14. float xdpi = dm.xdpi;             
  15. float ydpi = dm.ydpi;  
  16.   
  17. Log.e(TAG + "  DisplayMetrics""xdpi=" + xdpi + "; ydpi=" + ydpi);  
  18. Log.e(TAG + "  DisplayMetrics""density=" + density + "; densityDPI=" + densityDPI);  
  19.   
  20. screenWidth  = dm.widthPixels;      // 屏幕寬(像素,如:480px)  
  21. screenHeight = dm.heightPixels;     // 屏幕高(像素,如:800px)  
  22.   
  23. Log.e(TAG + "  DisplayMetrics(111)""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  
  24.   
  25.   
  26.   
  27. // 獲取屏幕密度(方法3)  
  28. dm = new DisplayMetrics();  
  29. getWindowManager().getDefaultDisplay().getMetrics(dm);  
  30.   
  31. density  = dm.density;      // 屏幕密度(像素比例:0.75/1.0/1.5/2.0)  
  32. densityDPI = dm.densityDpi;     // 屏幕密度(每寸像素:120/160/240/320)  
  33. xdpi = dm.xdpi;           
  34. ydpi = dm.ydpi;  
  35.   
  36. Log.e(TAG + "  DisplayMetrics""xdpi=" + xdpi + "; ydpi=" + ydpi);  
  37. Log.e(TAG + "  DisplayMetrics""density=" + density + "; densityDPI=" + densityDPI);  
  38.   
  39. int screenWidthDip = dm.widthPixels;        // 屏幕寬(dip,如:320dip)  
  40. int screenHeightDip = dm.heightPixels;      // 屏幕寬(dip,如:533dip)  
  41.   
  42. Log.e(TAG + "  DisplayMetrics(222)""screenWidthDip=" + screenWidthDip + "; screenHeightDip=" + screenHeightDip);  
  43.   
  44. screenWidth  = (int)(dm.widthPixels * density + 0.5f);      // 屏幕寬(px,如:480px)  
  45. screenHeight = (int)(dm.heightPixels * density + 0.5f);     // 屏幕高(px,如:800px)  
  46.   
  47. Log.e(TAG + "  DisplayMetrics(222)""screenWidth=" + screenWidth + "; screenHeight=" + screenHeight);  

 
重中之重:
density值表示每英寸有多少個顯示點,與分辨率是兩個不同的概念:

Android主要有以下幾種屏:

QVGA和WQVGA屏density=120;

HVGA屏density=160;

WVGA屏density=240;

下面以480dip*800dip的WVGA(density=240)爲例,詳細列出不同density下屏幕分辨率信息:

當density=120時 屏幕實際分辨率爲240px*400px (兩個點對應一個分辨率)
狀態欄和標題欄高各19px或者25dip
橫屏是屏幕寬度400px 或者800dip,工作區域高度211px或者480dip
豎屏時屏幕寬度240px或者480dip,工作區域高度381px或者775dip

density=160時 屏幕實際分辨率爲320px*533px (3個點對應兩個分辨率)
狀態欄和標題欄高個25px或者25dip
橫屏是屏幕寬度533px 或者800dip,工作區域高度295px或者480dip
豎屏時屏幕寬度320px或者480dip,工作區域高度508px或者775dip

density=240時 屏幕實際分辨率爲480px*800px (一個點對於一個分辨率)
狀態欄和標題欄高個38px或者25dip
橫屏是屏幕寬度800px 或者800dip,工作區域高度442px或者480dip
豎屏時屏幕寬度480px或者480dip,工作區域高度762px或者775dip

apk的資源包中,當屏幕density=240時使用hdpi標籤的資源
當屏幕density=160時,使用mdpi標籤的資源
當屏幕density=120時,使用ldpi標籤的資源。
不加任何標籤的資源是各種分辨率情況下共用的。
建議:佈局時儘量使用單位dip,少使用px。

device independent pixels(設備獨立像素). 不同設備有不同的顯示效果,這個和設備硬件有關,一般我們爲了支持WVGA、HVGA和QVGA 推薦使用這個,不依賴像素。

發佈了13 篇原創文章 · 獲贊 6 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章