Android中px、sp、dip的区别

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

[java] view plaincopyprint?
// TypedValue 中的这个函数负责将dp,sp,px等维度信息转换成像素   
  
public static int complexToDimensionPixelSize(int data,  
  
        DisplayMetrics metrics)  
  
   {  
  
     final float value = complexToFloat(data);  
  
     final float f = applyDimension(  
  
           (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,  
  
           value,  
  
           metrics);           // 这个函数负责完成转换,其实现请往下看   
  
     final int res = (int)(f+0.5f);  // 这里作了一个四舍五入   
  
     if (res != 0) return res;  
  
     if (value == 0) return 0;  
  
     if (value > 0) return 1;  
  
     return -1;  
  
}  
  
  
  
// 从这个函数的实现能够看出android系统对dp和sp处理的区别   
public static float applyDimension(int unit, float value,  
  
                              DisplayMetrics metrics)  
  
   {  
  
     switch (unit) {  
  
     case COMPLEX_UNIT_PX:  
  
        return value;   // px不须要作转换   
  
     case COMPLEX_UNIT_DIP:  
  
        return value * metrics.density;   // dp转换成px   
  
     case COMPLEX_UNIT_SP:  
  
        return value * metrics.scaledDensity;  // sp转换成px   
  
     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;  
  
}

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

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

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

二、 特定机型的density是肯定的,其取值取决于dpi,函数

若是dpi == 160, 则density = 1; 布局

若是dpi == 120, 则density = 0.75; 字体

若是dpi = 320, 则density = 2; spa

依次类推,也就是说code

density = (dpi*1.0)/ 160;开发

三、至于scaleDensity, android源码中的解释以下:

[java] view plaincopyprint?
/** 
 
   * 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属性同样,惟一不一样的地方是density对于特定机型是肯定的,是不会变化的,

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

四、至此,咱们就基本明白了sp和dp的区别,在不少android书籍中,都会说到若是是字体的大小开发者应该使

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

在运行时肯定是有可能引起布局混乱的。若是想获得无论用户如何设置偏好字体大小,咱们开发的应用的字体大

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

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

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

[java] view plaincopyprint?
public static final int dp2px(float dp, Resources res)  
  
 {  
  
  return (int) (dp * res.getDisplayMetrics().density + 0.5f);  
  
 }  
  
   
public static final int sp2px(float sp, Resources res)  
  
 {  
  
  return (int) (sp * res.getDisplayMetrics().scaledDensity+ 0.5f);  
  
 }
相关文章
相关标签/搜索