dp值主要用来描述控件的大小,确保在不同的设备屏幕下,所展示的控件大小基本一致。
sp值则专门用来设置字体的大小。
我们参考TypeValue类中的applyDimension方法来分析sp与dp的区别。
这个方法是用来将对应的参数值转换为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(dip)的转换公式为value*metrics.density。而sp的转换公式为value*metrics.scaledDensity。
所以sp与dp的差别,事实上就是density与scaledDensity的区别。
我们再来看scaledDensity的注解:
/**
* A scaling factor for fonts displayed on the display. This is the same
* as {@link #density}, except that it may be adjusted in smaller
* increments at runtime based on a user preference for the font size.
*/
public float scaledDensity;
所以,当用户设置字体为默认值的时候,density与scaledDensity是相等的。
我这里使用华为MT7进行具体真机的测试。
对应的density=3.0,
字体默认为:标准,scaledDensity=3.0。这与density相等。
改变字体偏好:
小:scaledDensity=2.5500002,大致是标准的0.85
大:scaledDensity=3.4499998,大致是标准的1.15
超大:scaledDensity=3.8999999, 大致是标准的1.3
特大:scaledDensity=3.90003,大致也是标准的1.3
特大字体与超大字体差别并不大,具体到显示上也的确如此。此处不知为何华为要加设一个特大字体,而事实上和超大也没多大差别。
再使用虚拟机模拟测试,这个虚拟机的density=3.5
字体默认为:正常,scaledDensity=3.5。
小:scaledDensity=2.9750001,大致是标准的0.85
大:scaledDensity=4.025,刚好是标准的1.15
超大:scaledDensity=4.549997, 大致是标准的1.3
虚拟机中没有特大选项。
由此我们也可以推知: