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
, ordp
units 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). UseRelativeLayout
instead. - Supply alternative bitmap drawables for different screen densities
另外一篇关于网页上字体大小单位的讨论:Font Size in Html - Px, Em, Rem。