Android解析度適配,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)
例如一個240dpi的螢幕,1dp就相當於1.5個像素
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”