px :是屏幕的像素點
in :英寸
mm :毫米
pt :磅,1/72 英寸
dp :一個基於density的抽象單位,如果一個160dpi的屏幕,1dp=1px
dip :等同於dp
sp :同dp相似,但還會根據用戶的字體大小偏好來縮放。
建議使用sp作為文本的單位,其它用dip
針對dip和px 的關系,做以下概述:
下面是一些分辨率信息 density就是屏幕密度
名稱 | 分辨率 | 屏幕密度 |
QVGA | 320*240 | 120 |
WQVGA400 | 400*240 | 120 |
WQVGA432 | 432*240 | 120 |
HVGA | 640*480 | 160 |
WSVGA | 1024*600 | 160 |
WXGA800 | 1280*800 | 160 |
WVGA800 | 800*480 | 240 |
WVGA854 | 854*480 | 240 |
WXGA720 | 1280*720 | 320 |
density值表示每英寸有多少個顯示點,與分辨率是兩個概念。
不同density下屏幕分辨率信息,以480dip*800dip的 WVGA(density=240)為例
下面以幾個真實機器來加深一下相關概念的認知
三星i5801 | HTC wildfire S(g13) | HTC sensation(g14) | meizu m9 | |
---|---|---|---|---|
分辨率 | 240*400 | 320*480 | 540*960 | 640*960 |
屏幕尺寸 | 3.2英寸 | 3.2英寸 | 4.3英寸 | 3.5英寸 |
屏幕密度 | 145.77 | 180.27 | 256.15 | 329.65 |
DisplayMetrics得出的DPI | 120 | 160 | 240 | 320 |
黃色部分為使用上述公式計算的屏幕密度,綠色部分為使用DisplayMetrics得出的dpi,可以看到比較接近
有兩方面的原因,導致這兩個數據不一致
1.廠商給出的屏幕尺寸參數不是太精確
2.DisplayMetrics中定義的密度值只有120、160、213、240、320
----------------------------------------
這里從另一個角度可以進行屏幕尺寸的反推,以meizu m9為例,通過DisplayMetrics可以得到其xdpi和ydpi均為325.12
這樣屏幕寬度=640/325.12=1.9685英寸,屏幕高度=960/325.12=2.9527英寸
使用勾股定理計算得出,對角線尺寸為3.5487英寸
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
dp與px換算公式:
pixs =dips * (densityDpi/160).
dips=(pixs*160)/densityDpi
dp與px轉換的方法:
public static int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(dipValue * scale +0.5f);
}
public static int px2dip(Context context, float pxValue){
final float scale = context.getResource().getDisplayMetrics().density;
return (int)(pxValue / scale +0.5f);
}
名詞 |
解釋 |
Px (Pixel像素) |
不同設備顯示效果相同。這里的“相同”是指像素數不會變,比如指定UI長度是100px,那不管分辨率是多少UI長度都是100px。也正是因為如此才造成了UI在小分辨率設備上被放大而失真,在大分辨率上被縮小。 |
Screen Size (屏幕尺寸) |
一般所說的手機屏幕大小如1.6英寸、1.9英寸、2.2英寸,都是指的對角線的長度,而不是手機面積。我們可以根據勾股定理獲取手機的寬和長,當然還有面積。 |
Resolution (分辨率) |
指手機屏幕垂直和水平方向上的像素個數。比如分辨率是480*320,則指設備垂直方向有480個像素點,水平方向有320個像素點。 |
Dpi (dots per inch 像素密度) |
指每英寸中的像素數。如160dpi指手機水平或垂直方向上每英寸距離有160個像素點。假定設備分辨率為320*240,屏幕長2英寸寬1.5英寸,dpi=320/2=240/1.5=160 注意:該值對應於DisplayMetrics類中屬性densityDpi的值 |
Density (密度) |
指每平方英寸中的像素數。 Density=Resolution/Screen size 注意:在DisplayMetrics類中屬性density的值為dpi/160,可用於px與dip的互相轉換 |
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 作為字號單位。 |