Android开发中使用的度量单位px、dp、sp、pt、in、mm
关于多屏的支持,最好的文章当然是官方文档:Supporting Multiple Screens。一篇文章,从概念到解决方案,非常全面。
下面主要讨论一下开发过程中使用的度量单位的问题。
单位的意义及其之间的转换
对于不同的度量单位(px、dp、sp、pt、in、mm),可以从下面一张图看出它们之间的关系:

左上->右上->左下->右下,依次为ldpi->mdpi->hdpi->xhdpi(其大小不代表绝对大小,只用关注它们之间的相对大小即可)。结论如下:
px
px是唯一一个显示大小与dpi有关系的单位,其它单位的显示大小都与dpi无关。
dp
dp也叫dip,即density-independent-pixel,在dpi等于160的时候,其大小与px相等。因此,我们可以算出1dp等于densityDpi / DENSITY_DEFAULT(160)) px,也就是density px。具体关系参考下面介绍DisplayMetrics中属性的表格。
sp
除了具有dp的特征之外,sp还可以响应用户的font size preference设置其值像dp一样,也只能取一些离散的值。font size preference的设置界面如下:

pt、in、mm
这几个单位都是长度单位,其中pt等于1/72inch,都是用户最终看到的大小。这些值都是根据设备真实物理像素密度(xdpi和ydpi)算出来的,不会像dp和sp一样,只有几个离散的值。
在TypedValue.java中有所有单位到px的转换方法:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |  | 
该函数将所有的单位转换为px,其中参数意义如下:
| 属性 | 意义 | 
|---|---|
| metrics.density | 默认值为 densityDpi / (float) DENSITY_DEFAULT。该值为归整之后的值:比如150dpi的设备,density值为1,即按照160dpi进行处理。density的典型值为0.75、1.0、1.5、2.0、3.0等。 | 
| metrics.densityDpi | 设备物理像素密度,非精确的归整值,可取值为 DENSITY_LOW(120)、DENSITY_MEDIUM(160)、DENSITY_HIGH(240)等。density的值是根据densityDpi / DENSITY_DEFAULT计算出来的,所以取值也是一些典型的离散值。 | 
| metrics.scaledDensity | 具有 density所有的特征,如果用户设置了font size preference,还需要乘以一个scale系数。 | 
| metrics.xdpi | x方向的物理像素密度,精确的值,单位px/inch。同样的有ydpi。 | 
| DENSITY_DEFAULT | dpi的参考值,值为160px/inch。 | 
dp转换为px
有时候我们必须使用px作为单位,比如某个api接受的参数只能是px。这个时候,需要将dp转化为px。在code中我们可以使用下面的方法将dp转化为px:
| 1 2 3 4 5 6 7 8 9 |  | 
Best Practice
- Use wrap_content,match_parent, ordpunits when specifying dimensions in an XML layout file
- Do not use hard coded pixel values in your application code
- Do not use AbsoluteLayout(it’s deprecated). UseRelativeLayoutinstead.
- Supply alternative bitmap drawables for different screen densities
另外一篇关于网页上字体大小单位的讨论:Font Size in Html - Px, Em, Rem。