Android分辨率適配

Android的分辨率適配問題一直是Android所讓人詬病的主要問題,這裡參考瞭官方的開發文檔和實際開發中的一些處理分辨率的技巧來和大傢交流一下。

官方的關於分辨率適配的文檔“SupportingMultiple Screens”

Overview of Screens Support

Screen size:屏幕尺寸 Screen density:屏幕密度 Orientation:方向 Resolution:分辨率 Density-independent pixel (dp or dip):與像素類似的一個概念,是組成畫面的最小顆粒度的單位,相當於160dpi屏幕上的一個物理像素點

Range of screens supported

Android從1.6(API Level 4)開始支持多分辨率適配,對屏幕尺寸和密度進行瞭劃分:
* 屏幕尺寸:small,normal,large,xlarge
* 屏幕密度:ldpi(low),mdpi(medium),hdpi(high),xhdpi(extra high)

這裡寫圖片描述

這裡尺寸和密度的基準是基於第一臺Android機T-Mobile G1(HVGA Screen),所以為瞭減少產品的適配成本,隻需要考慮在generailized size/density上的適配性。

在設計實際的Layout的時候,應該用的單位是dp,這樣就可以避免因為屏幕的dpi不同所造成的影響,最典型的例子就是蘋果的retina屏幕。

xlarge: at least 960dp x 720dp large: at least 640dp x 480dp normal: at least 470dp x 320dp small: at least 426dp x 320dp

這裡寫圖片描述

px = dp * (dpi / 160)vc3Ryb25nPjwvcD4NCgk8cD7A/cjn0ru49jI0MGRwabXExsHEu6OsMWRwvs3P4LWx09oxLjW49s/xy9g8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8aDQgaWQ9″pxdpidpdipsp”>px,dpi,dp,dip,sp

度量單位 解釋
px(pixel像素) 像素單位
dpi(dots per inch像素密度) 每英寸的像素數,假設設備的分辨率是320 * 240,屏幕長2英寸寬1.5英寸,dpi=320/2=240/1.5=160
dp(density密度) 每平凡英寸的像素數Density=Resolution/Screen size
dip(Device-independent pixel,設備獨立像素) 和dp相同,不同設備有不同的顯示效果,這個和設備硬件有關,一般我們為瞭支持WVGA、HVGA和QVGA 推薦使用這個,不依賴像素。dip和具體像素值的對應公式是dip值 =設備密度/160* pixel值,可以看出在dpi(像素密度)為160dpi的設備上1px=1dip
sp(ScaledPixels放大像素) 主要用於字體顯示(best for textsize)。根據 google 的建議,TextView 的字號最好使用 sp 做單位,而且查看TextView的源碼可知 Android 默認使用 sp 作為字號單位。
屏幕 密度 dpi 分辨率 匹配分組
QVGA density=0.75 densityDpi=120 QVGA(240 * 320) ldpi
HVGA density=1.0 densityDpi=160 HVGA(320 * 480) mdpi
VGA density=1.0 densityDpi=160 VGA(480 * 640) mdpi
WVGA density=1.5 densityDpi=240 WVGA(480 * 800) hdpi
WQVGA density=2.0 densityDpi=120 WQVGA(240*400) xhdpi

為什麼在設計UI的時候要考慮dpi

這裡舉一個例子,在沒有考慮dpi的情況下在界面上放一個32 * 32px大小的按鈕,那麼在同樣是3.7寸,分辨率分別是480 * 320、600 * 480、800 * 600的手機的顯示效果如下:

這裡寫圖片描述

由圖可以看出,由於設備的dpi增大,1px在設備上對應的物理長度減少,最終的顯示效果是組件看起來變小瞭。

用dpi來作為界面的尺寸標註單位

將控件的尺寸標註為32dip * 32dip,得到的顯示效果:

這裡寫圖片描述

可以看出顯示的效果好瞭很多。Android默認是使用density來匹配資源文件,而不是屏幕大小,同時圖片分辨率和屏幕不匹配時,系統為需要大量的額外內存來對圖像進行拉伸和縮放,這些額外的開銷,會降低程序運行的效率。最關健是可能會引起內存溢出的異常,這是由android內存回收機制引起,對於大量圖片使用的情況,發生的概率相當的高,目前沒有有效辦法解決。

獲取density和dip

手機density和DIP可以使用以下方法獲取,兩種方法,一種是getWindowManager獲取,一種是通過getResources的獲取,兩種結果是一樣的,但因為某些原因,可能會有差異,有些手機廠商會修改API,有些廠商無良廠商會讓低端屏故意顯示高端的數據,如果你獲取的屏幕數據不太準確,也不必太過在意:

void getDefaultDisplayScreenSize()
{
    DisplayMetrics dm = newDisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    int screenWidthDip = dm.widthPixels;// 屏幕寬(dip,如:320dip)
    int screenHeightDip = dm.heightPixels;// 屏幕寬(dip,如:533dip)

    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;

    w= dm.widthPixels;// 屏幕寬(px,如:480px)
    h= dm.heightPixels;// 屏幕高(px,如:800px)
}

void getDefaultDisplayScreenDensityDPI()
{
    DisplayMetricsdm = newDisplayMetrics();
    getResources().getDisplayMetrics();

    int screenWidthDip = dm.widthPixels;// 屏幕寬(dip,如:320dip)
    int screenHeightDip = dm.heightPixels;// 屏幕寬(dip,如:533dip)

    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;
}

屏幕適配的流程

1、聲明應用兼容的屏幕尺寸
在manifest文件中用來聲明應用兼容的屏幕尺寸。這樣可以讓設備判斷是否采用屏幕兼容性模式(Screen Compatibility Mode)來運行應用。

2、為不同的屏幕尺寸提供不同的Layout佈局
對面的佈局文件分別放在layout-small,layout-normal,layout-large,layout-xlarge文件夾下。

3、為不同的dpi提供不同的圖片資源
如果是用dip來標記組件的大小,在繪制圖片的時候,會將以像素尺寸度量大小的圖片資源做縮放操作來最終適應屏幕中組件的大小,很容易產生顯示模糊、圓角變形等問題,所以會針對不同dpi準備不同的圖片資源。如果為不同dpi設備準備瞭不同的圖片資源,android參考文檔中建議以3:4:6:8的比例來依次做ldpi,mdpi,hdpi和xhdpi上的資源,android官方有關參考文檔“IconDesign Guidelines”

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *