Android中的常用尺寸单位(dp、sp)快速入门教程
常见尺寸单位
Android开发中的常用尺寸单位有如下几种:
- dp (dip)
- px
- pt
- inch
- sp
算不知道确切含义,相信对于以上这几种尺寸单位大家也都比较脸熟,这里先让我们重新认识一下它们:
- dp (dip): 即设备无关像素(device independent pixels),这种尺寸单位在不同设备上的物理大小相同。
- px:即像素(pixel),这个不用多说。
- pt:通常用来作为字体的尺寸单位,1 pt相当于1/72英寸。
- inch:英寸,1 英寸约等于2.54厘米,主要用来描述手机屏幕的大小。
- sp:大部分人只知道它通常用作字体的尺寸单位,实际大小还与具体设备上的用户设定有关。(如果你对"sp"的了解停留于此,那么看完这篇文章后你会更透彻的理解它^ _ ^)
在上面几种常见的尺寸单位,dp和sp可以看做是虚拟尺寸。其中dp是与设备无关的虚拟像素单位,开发者为UI控件指定以dp为单位的大小后,在不同屏幕密度的Android设备上便能够具有相同的物理尺寸。dp的出现让开发者无需关注屏幕密度、物理像素之间的换算关系。sp则与dp相似,但它主要用作字体的尺寸单位,与dp的区别是:Android系统支持用户设定字体大小,因而sp的实际大小还会根据用户设定在原基础上进行缩放。
下面来详细介绍dp与sp这两种尺寸单位。
尺寸单位详解之dp
dp的全称是device independent pixels,在具有不同屏幕密度的设备上,1 dp的物理大小是相同的。那么,什么是屏幕密度呢?
屏幕密度
手机的屏幕密度通常指的是手机屏幕的dpi(dots per inch),也就是每英寸的像素数。对于Android手机来说,常见的dpi有如下几种:
- ldpi:对应的dpi范围为0 ~ 120,也就是说每英寸有0到120个像素点的屏幕的屏幕密度都属于ldpi
- mdpi:dpi范围为120 ~ 160
- hdpi:dpi范围为160 ~ 240
- xhdpi:dpi范围为240~320
- xxhdpi:dpi范围为320~480
在实际开发中,通常以dpi值120、160、240、320、480分别指代ldpi、mdpi、hdpi、xhdpi、xxhdpi。通常屏幕密度越大的手机显示的图像会越细腻。可以通过如下代码获取当前Android设备的屏幕密度:
private void getDpi() { DisplayMetrics dm = getResources().getDisplayMetrics(); Log.i("TAG", "density = " + dm.density); Log.i("TAG", "densityDpi = " + dm.densityDpi); }
若我们在一台屏幕密度为320dpi的Android手机上运行以上代码,会得到如下输出:
density = 2 densityDpi = 320
上面输出中的densityDpi就是Android手机屏幕的dpi值,那么density是什么呢?实际上它代表的是当前屏幕的dpi值与基准dpi值的比值,这个基准dpi值为160。
现在我们已经理解了dpi,接下来让我们揭开dp的神秘面纱。
dp
上面我们提到了选择dpi值160作为基准屏幕密度,这个基准屏幕密度人为建立起了dp与px间的关系:在dpi为160的Android设备上,1 dp = 1px。假设x为某UI控件以px为单位的大小,y为同一UI控件以dp为单位的大小,densityDpi表示屏幕密度,则x与y的关系为:x = y * densityDpi / 160。
介绍完了dp,接下来让我们探究一下sp这个尺寸单位的真面目。
尺寸单位详解之sp
在介绍sp之前,我们先来一起看下TypedValue类中包含的一个用户将dp、sp等单位转换为px的静态方法:
public static float applyDimension(int unit, float value,DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }
若要将dp转换为px,会执行如下代码:
return value * metrics.density;
density我们在前面介绍过,指的是当前dpi与基准dpi(160)的比值。density的计算方式就是当前屏幕的dpi除以160。也就是说,在屏幕的dpi为120、160、320、480时,density的值分别为0.75、1、2、3。
若要将sp转换为px,则会执行如下代码:
return value * metrics.scaledDensity;
可以看到,sp转换为px的计算公式与dp转换为px时相似,那么scaledDensity是什么呢?实际上,scaledDensity不同于density,scaledDensity是可以动态改变的,当用户改变了Android设备的字体缩放比例时,scaledDensity的值就会发生变化。scaledDensity的计算公式为:scaledDensity = density * fontScale。其中fontScale代表用户设定的Android设备字体缩放比例,默认为1。也就是说,当用户没有改变Android设备的字体缩放比例时,sp、dp与px的换算是相同的。
多分辨率之殇
市面上存在着的各种不同分辨率的Android设备为广大Android开发者挖了众多的坑,比如:
- 需要为不同分辨率的Android设备单独维护一套dimens文件;
- 通常UI设计师只会针对某种特定分辨率的设备为我们标注UI控件的像素大小,相信不少小伙伴都受够了手动换算不同分辨率设备上UI控件像素大小的痛苦;
- 通常我们需要为每种分辨率的Android设备维护一个drawable文件夹以获得比较好的图片显示效果,这会导致apk文件尺寸的臃肿;而且若某个drawable文件夹下的图片需要修改,那么就需要替换其他所有drawable文件夹中对应的图片。如果不小心漏掉了某个drawable文件夹下的图片,则会导致该图片在某些分辨率的手机上失真。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
相关文章
Android程序开发之ListView实现横向滚动(带表头与固定列)
这篇文章主要介绍了Android程序开发之ListView实现横向滚动(带表头与固定列)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下2016-07-07Android使用google breakpad捕获分析native cash
这篇文章主要介绍了Android使用google breakpad捕获分析native cash 的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下2019-04-04
最新评论