1,一段常见的代码
关于Android中的大小尺寸,我们可能最常接触的概念就是sp,dip,px。而最常使用的代码就是px与dip二者的相互转化,以及px与sp之间的相互转化,如下:
对于大多对android开发人员都很熟悉上面的代码,如果你不认识,那也没关系,接下来从各个基础概念讲起。
2,px,dip的关系
px,像素,英文简称pixel,简写自picture element,像很多文章中所说,像素就是图片中的一个点。
dip ,全称Density-independent Pixels。只要在布局中文件使用到大小,距离,官方都推荐使用dip(除了字体大小),一般我们对dip和dp不做区别。dip这个单位是为了使同样数量的px在不同手机上的显示效果相同,显然1 dip是1 px通过某种对应关系转化过来的。这种转化上面的代码已经有了,但是其原理是什么呢?这就得引出另一个概念dpi(dots per inch)
dpi,官方文档对这个单位的指代是Screen density,即屏幕密度,表示一个物理单位面积内像素点的个数。而在160dpi的设备上,1dip = 1px,在120dpi的设备上,1dip = 0.75px,没错,这就是px和dip对应关系的基础,dpi越大,1dip内就有更多的px。
dpi类别 | dpi大小 | px | dp | 物理显示大小 |
---|---|---|---|---|
ldpi | 120dpi | 120px | 160dp | 1个单位 |
mdpi | 160dpi | 160px | 160dp | 1个单位 |
hdpi | 240dpi | 240px | 160dp | 1个单位 |
xhdpi | 320dpi | 320px | 160dp | 1个单位 |
xxhdpi | 480dpi | 480px | 160dp | 1个单位 |
从上面这个表可以看出,在不同dpi的手机上,相同的的dp可以对应相应的物理大小,从而发挥了适配不同设备的作用。
从上面的对应关系,不难得出如下公式
px = dp * dpi / 160
那么再来看一下上面dp和px的转化代码。
context.getResources().getDisplayMetrics()返回的是一个DisplayMetrics对象,该对象有这么三个成员变量
densityDpi就是上面的dpi,density是当前设备和默认dpi = 160的比值,比如,对于dpi = 320的设备,densityDpi = 320,density = 2。scaledDensity是和sp有关的参数,下面再讲。
再回头仔细看这段用于单位转化的代码,而刚刚得出的公式是不是一致的,没错,就是一样的,只是多了一个0.5,这个是为了四舍五入而已。到此为止,应该就理解了px和dp之间的关系了。
于是乎,应该也能理解android项目中的图片资源文件,一般我们需要在以下几个文件夹中提供不同大小的图片。
- xhdpi: 2.0
- hdpi: 1.5
- mdpi: 1.0 (baseline)
- ldpi: 0.75
如果你想要提供一张大小为200x200的照片给xhdpi的设备, 那相对应的就得提供一张150150的照片给hdpi的设备,提供100100给mdpi,提供7575给ldpi*。
再谈一个问题。大家一般都将图片文件按如下结构放在项目中。
但是在最新的ADT中新建会见到下面这种结构
其实很简单,mipmap是用来放置app的icon图标的。其他资源图片文件也可以放在这里面,但是最好还是新建一个drawable的结构。真相在这个链接
http://developer.android.com/training/multiscreen/screendensities.html
3. sp
sp的全称Scale-independent Pixels,布局文件中对TextView指定字体大小时,都建议使用sp.sp与dip相比多考虑了手机字体大小的偏好设置。而sp与px的转化关系,与dp和px的转化关系,只是对应的比例参数从density变成了scaledDensity原理是一样的。
4。举例
这里举个特例,加深理解。
如果一个hdpi设备,在drawable-hdpi文件夹中没图片,反而在drawable-xhdpi文件夹中存在,那么加载到内存的图片会相比在drawable-hdpi的图片会变小一半,占用内存也会变小(变成四分之一),
另外,再注意一点,一个ImageView控件,修改其layout_height和layout_width的值,图片显示大小会变化,但是像素,占用内存不会变化。
下面是我写的一个小demo的截图,可以参考参考,加深理解:
这是一个hdpi的设备,第一幅图加载hdpi的图片,第二幅图加载xhdpi的图片,第三幅图加载xhdpi图片但是指定了长宽。
此处getWidth,getHeigth返回的是图片长宽,单位是像素,单位是px,而非dip。
4,参考链接
http://developer.android.com/guide/practices/screens_support.html
http://developer.android.com/training/multiscreen/screendensities.html
http://www.cnblogs.com/yaozhongxiao/archive/2014/07/14/3842908.html