Android中px、sp、dip的区别

来源:互联网 发布:金蝶k3无法数据引出 编辑:程序博客网 时间:2024/06/05 19:14

转自: http://blog.csdn.net/ericming200409/article/details/19686195

刚刚接触android开发的同学,在做UI开发的时候都会碰到各种度量单位----px, dp, sp,网上有很多文章讲述这三者的不同,当初我刚开始接触android开发的时候,正是通过网上的这些资料了解他们的区别的,但是看完之后仍然不是很明了的感觉,究其原因,是因为大部分文章都是从“其然”的角度来阐述的,让读者不知其所以然。本文试图从android实现的角度来阐述这三者的区别。

不管我们开发者使用哪个度量单位,最后经过android系统的处理,都是要转换成像素单位的,也就是px。而在android中,负责实现这一转换过程的函数如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. // TypedValue 中的这个函数负责将dp,sp,px等维度信息转换成像素  
  2.   
  3. public static int complexToDimensionPixelSize(int data,  
  4.   
  5.         DisplayMetrics metrics)  
  6.   
  7.    {  
  8.   
  9.      final float value = complexToFloat(data);  
  10.   
  11.      final float f = applyDimension(  
  12.   
  13.            (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,  
  14.   
  15.            value,  
  16.   
  17.            metrics);           // 这个函数负责完成转换,其实现请往下看  
  18.   
  19.      final int res = (int)(f+0.5f);  // 这里做了一个四舍五入  
  20.   
  21.      if (res != 0return res;  
  22.   
  23.      if (value == 0return 0;  
  24.   
  25.      if (value > 0return 1;  
  26.   
  27.      return -1;  
  28.   
  29. }  
  30.   
  31.   
  32.   
  33. // 从这个函数的实现可以看出android系统对dp和sp处理的区别  
  34. public static float applyDimension(int unit, float value,  
  35.   
  36.                               DisplayMetrics metrics)  
  37.   
  38.    {  
  39.   
  40.      switch (unit) {  
  41.   
  42.      case COMPLEX_UNIT_PX:  
  43.   
  44.         return value;   // px不需要做转换  
  45.   
  46.      case COMPLEX_UNIT_DIP:  
  47.   
  48.         return value * metrics.density;   // dp转换成px  
  49.   
  50.      case COMPLEX_UNIT_SP:  
  51.   
  52.         return value * metrics.scaledDensity;  // sp转换成px  
  53.   
  54.      case COMPLEX_UNIT_PT:  
  55.   
  56.         return value * metrics.xdpi * (1.0f/72);  
  57.   
  58.      case COMPLEX_UNIT_IN:  
  59.   
  60.         return value * metrics.xdpi;  
  61.   
  62.      case COMPLEX_UNIT_MM:  
  63.   
  64.         return value * metrics.xdpi * (1.0f/25.4f);  
  65.   
  66.      }  
  67.   
  68.      return 0;  
  69.   
  70. }  

看完上述两个函数,有一定基础的同学相信已经一目了然,不过这里我还是做一下详细介绍:

1、 DisplayMetrics是一个封装了屏幕属性的数据结构,其中有屏幕的高度、宽度、dpi(每英寸像素个数)、已及

上面函数中用到的density、scaledDensity等信息;

2、 特定机型的density是确定的,其取值取决于dpi,

如果dpi == 160, 则density = 1; 

如果dpi == 120, 则density = 0.75; 

如果dpi = 320, 则density = 2; 

依次类推,也就是说

density = (dpi*1.0)/ 160;

3、至于scaleDensity, android源码中的解释如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  
  3.    * A scaling factor for fonts displayed on the display.  This is the same 
  4.  
  5.    * as {@link #density}, except that it may be adjusted in smaller 
  6.  
  7.    * increments at runtime based on a user preference for the font size. 
  8.  
  9.    */  
  10.   
  11.    public float scaledDensity;  

也就是说,这个属性基本和density属性一样,唯一不同的地方是density对于特定机型是确定的,是不会变化的,

而scaleDensity是运行时确定的,是会跟这用户设置的偏好字体大小变化的。

4、至此,我们就基本明白了sp和dp的区别,在很多android书籍中,都会说到如果是字体的大小开发者应该使

用sp作为单位,甚至android官方文档也这么说,我认为这纯属是在误导人,因为sp是运行时确定的,字体大小

在运行时确定是有可能引发布局混乱的。如果想得到不管用户如何设置偏好字体大小,我们开发的应用的字体大

小都不变就应该使用dp,而不是sp。

5、我们在开发过程中,经常需要用到这些度量单位的转换,其实理解这些单位之间的区别以及android对这些单

位的转换之后,要实现转换函数是很简单的了

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public static final int dp2px(float dp, Resources res)  
  2.   
  3.  {  
  4.   
  5.   return (int) (dp * res.getDisplayMetrics().density + 0.5f);  
  6.   
  7.  }  
  8.   
  9.   
  10.   
  11. public static final int sp2px(float sp, Resources res)  
  12.   
  13.  {  
  14.   
  15.   return (int) (sp * res.getDisplayMetrics().scaledDensity+ 0.5f);  
  16.   
  17.  }  
0 0
原创粉丝点击