天天看點

android分辨率問題

一、Android手機目前常見的分辨率

4:3

VGA 640*480 (Video Graphics Array)

QVGA 320*240 (Quarter VGA)

HVGA 480*320 (Half-size VGA)

SVGA 800*600 (Super VGA)

5:3

WVGA 800*480 (Wide VGA)

16:9

FWVGA 854*480 (Full Wide VGA)

HD 1920*1080 High Definition

QHD 960*540

720p 1280*720 标清

1080p 1920*1080 高清

分辨率對應DPI

HVGA mdpi 160dpi

WVGA hdpi 240dpi

FWVGA hdpi 240dpi

QHD hdpi 240dpi

720P xhdpi 320dpi

1080P xxhdpi 480dpi

二、遇到一個問題,我的地圖浮标圖檔在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/ 320)
           
但是,需要注意的是,在一個低密度的小屏手機上,僅靠上面的代碼是不能擷取正确的尺寸的。比如說,一部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程式就支援了多種分辨率,那麼就可以得到正确的實體尺寸了。
           

方法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;  

screenWidth  = dm.widthPixels;      // 螢幕寬(像素,如:480px)  
screenHeight = dm.heightPixels;     // 螢幕高(像素,如:800px)  
           

重中之重:

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

Android主要有以下幾種屏:

QVGA和WQVGA屏density=120;

HVGA屏density=160;

WVGA屏density=240;

當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=480時,使用xxhdpi的資源包

當螢幕density=320時,使用xhdpi标簽的資源

當螢幕density=240時,使用hdpi标簽的資源

當螢幕density=160時,使用mdpi标簽的資源

當螢幕density=120時,使用ldpi标簽的資源。

不加任何标簽的資源是各種分辨率情況下共用的。

建議:布局時盡量使用機關dip,少使用px。

三、螢幕适配的注意事項

1 基本設定

1.1.1 AndroidManifest.xml設定

在中Menifest中添加子元素

android:anyDensity=”true”時,應用程式安裝在不同密度的終端上時,程式會分别加載相應的xxhdpi、xhdpi、hdpi、mdpi、ldpi檔案夾中的資源。相反,如果設為false,即使在檔案夾下擁有相同資源,應用不會自動地去相應檔案夾下尋找資源,規則如下:

1.1.2 橫屏豎屏目錄區分

1) drawable

a) drawable-hdpi該圖檔即适用于橫屏,也适用于豎屏;

b) drawable-land-hdpi,當螢幕為橫屏,且為高密度時,加載此檔案夾的資源;

c) drawable-port-hdpi,當螢幕為豎屏,且為高密度時,加載此檔案夾中的資源。其他同理。

2) layout

在res目錄下建立layout-port和layout-land兩個目錄,裡面分别放置豎屏和橫屏兩種布局檔案,以适應對橫屏豎屏自動切換。

2.2 多螢幕适配的4條黃金原則

1) 在layout檔案中設定控件尺寸時應采用fill_parent、wrap_content、match_parent和dp;

具體來說,設定view的屬性android:layout_width和android:layout_height的值時,wrap_content,match_parent或dp比px更好,文字大小應該使用sp來定義。

2) 在程式的代碼中不要出現具體的像素值,在dimens.xml中定義;

為了使代碼簡單,android内部使用pix為機關表示控件的尺寸,但這是基于目前螢幕基礎上的。為了适應多種螢幕,android建議開發者不要使用具體的像素來表示控件尺寸。

3) 不使用AbsoluteLayout(android1.5已廢棄) ,可以使用RelativeLayout替代;

4) 對不同的螢幕提供合适大小的圖檔。

不同大小螢幕用不同大小的圖檔,low:medium:high:extra-high圖檔大小的比例為3:4:6:8;舉例來說,對于中等密度(medium)的螢幕你的圖檔像素大小為48×48,那麼低密度(low)螢幕的圖檔大小應為36×36,高(high)的為72×72,extra-high為96×96。

2.3 使用9-patch PNG圖檔

使用圖檔資源時,如果出現拉伸,因為圖檔處理的原因,會變形,導緻界面走形。9-patch PNG圖檔也是一種标準的PGN圖檔,在原生PNG圖檔四周空出一個像素間隔,用來辨別PNG圖檔中哪些部分可以拉伸、哪些不可以拉伸、背景上的邊框位置等。

“上、左”定義可拉伸區域

“右、下”定義顯示區域,如果用到完整填充的背景圖,建議不要通過android:padding來設定邊距,而是通過9-patch方式來定義。

Android SDK中提供了編輯9-Patch圖檔的工具,在tools目錄下draw9patch.bat,能夠立刻看到編輯後的拉伸效果,也可以直接用其他圖檔編輯工具編輯,但是看不到效果。

2.4 不同的layout

Android手機螢幕大小不一,有480x320, 640x360, 800x480……

怎樣才能讓Application自動适應不同的螢幕呢?

其實很簡單,隻需要在res目錄下建立不同的layout檔案夾,比如:layout-640x360、layout-800x480……所有的layout檔案在編譯之後都會寫入R.java裡,而系統會根據螢幕的大小自己選擇合适的layout進行使用。