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);  
  
 }
相關文章
相關標籤/搜索