我们在编写android的界面布局时,经常对px、dp、sp、像素密度、drawable、drawable-hdpi等等跟图像和像素相关的概念感到迷惑,下面就一一对这些概念进行解析。
1、px
屏幕上的(像素)点,分辨率为320*160的屏幕就表示横向有320个(像素)点,纵向有160个(像素)点,这是绝对像素点。
2、像素密度
每英寸屏幕所拥有的像素数(Pixels Per Inch),单位ppi/dpi,计算公式(√ 横向像素点数的平方+纵向像素点数的平方)/屏幕尺寸;
3、dp
dp指的是与屏幕像素密度无关的抽象像素,dp的引入是为了解决屏幕在不同像素密度下保持物理尺寸一致的问题,这个物理尺寸就是当屏幕像素密度为160dpi时绝对像素点(px)的物理尺寸;dp和px的转换公式:px = dpi/160 * dp;10dp在屏幕像素密度为160dpi时像素点为10px,假设现在10个像素点的物理长度为L,那么10dp在其他任何屏幕像素密度下占有的物理长度都为L。
4、sp
sp是与缩放无关的抽象像素(Scale-independent Pixel),用于字体大小的处理;sp和dp类似,但是dp与px的换算根据density ,而sp与px的换算则根据scaledDensity(缩放密度),换算的公式都是:px =(density 或 scaledDensity)* (dp 或 sp);其中density = getResources().getDisplayMetrics().density,scaledDensity =getResources().getDisplayMetrics().scaledDensity;density是根据屏幕像素密度/160得来的,是固定不变的;scaledDensity是根据字体设定的变化而变化的,下面是我在虚拟机上不同字体下scaledDensity的值;
字体:
小:0.85
普通:1
大:1.15
超大:1.3
所以在dp和sp同时使用的时候要注意系统字体的设置,有时字体大小会超出边界导致显示不全;
5、drawable-hdpi、drawable-ldpi、drawable-mdpi、drawable-xhdpi和drawable-xxhdpi的区别,系统如何处理这些文件夹下的资源文件;
android系统会在运行时根据当前的屏幕像素密度选择不同文件夹下的资源文件,用以适配不同的屏幕,drawable-hdpi、drawable-ldpi、drawable-mdpi等资源文件夹
的设计就是为了达到这个目的。那么问题来了,android系统是如何处理这几个文件下的资源文件的?
这里首先引入一个概念:基线像素密度,每一个文件夹都有一个基线像素密度,值如下示:
ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi
当屏幕像素密度为160dp时,android系统默认是取drawable-mdpi下的资源文件,要想搞清楚系统是如何处理取出的资源文件,下面先来看一个例子;
先选取5张图片,图片大小分别为:225*225、300*300、450*450、600*600、900*900,如下图示:
把五张图片分别放入drawable-ldpi、drawable-hdpi、drawable-mdpi、drawable-xhdpi和drawable-xxhdpi中,在程序中选择ImageView来显示图片,ImageView设置如下:
<ImageView
android:id="@+id/icon_main_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon" />
ImageView的长度和宽度都设为wrap_content,在屏幕密度为160dpi时,系统取出各资源文件夹下的图片显示情况如下示:
在屏幕密度为240dpi时,系统取出各资源文件夹下的图片显示情况如下示:
在屏幕密度为160dpi时不同尺寸的图片在屏幕上显示的尺寸都为300*300,而240dpi时显示的尺寸都为450*450,这里就可以推导出系统对资源文件处理的计算
公式:
设基线像素密度为Bd,屏幕像素密度为Sd,图片实际尺寸为Sl,那么系统处理图片后实际显示的尺寸为:
Dl = Sd /Bd * Sl