TypedValue.applyDimension 中dp和sp之間轉化的真相


   最近在看了許多關於dp-px,px-dp,sp-px,px-sp之間轉化的博文,過去我比較常用的方式是:

 1 //轉換dip為px 
 2 public static int convertDipOrPx(Context context, int dip) { 
 3     float scale = context.getResources().getDisplayMetrics().density; 
 4     return (int)(dip*scale + 0.5f*(dip>=0?1:-1)); 
 5 } 
 6  
 7 //轉換px為dip 
 8 public static int convertPxOrDip(Context context, int px) { 
 9     float scale = context.getResources().getDisplayMetrics().density; 
10     return (int)(px/scale + 0.5f*(px>=0?1:-1)); 
11 } 

然后看到了一種新的轉化方式,代碼如下:

1 public static int dp2sp(float dpVal){
2     return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
3             MyAppliction.getInstance().getApplicationContext().getResources().getDisplayMetrics()));
4 }
5  //?????
6 public static int sp2dp(float spVal){
7     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
8             MyAppliction.getInstance().getApplicationContext().getResources().getDisplayMetrics()));
9 }

碼農對TypedValue充滿好奇,通過查詢官網了解該類

TypedValue

  ---android.util.TypedValue
 
Container for a dynamically typed data value. Primarily used with Resources for holding resource values.

 翻譯過來就是:這個類是工具類,作為一個動態容器,它存放一些數據值,這些值主要是resource中的值。

我們來理解一下:resource中到底有哪些值?layout、drawable、string、style、anim、dimens、menu、colors、ids這些值一些和屏幕適配有直接的關系。

有一些方法必然是可以讀取這些資源文件信息的,比如:

getDimension(DisplayMetrics metrics)

再看具體的方法:

applyDimension(int unit, float value,DisplayMetrics metrics)
第一個參數是單位,第二個參數是對應值,第三個你懂的,封裝了顯示區域的各種屬性值。

對於applyDimension(int unit, float value,DisplayMetrics metrics)中的代碼我們來看下

 1  public static float applyDimension(int unit, float value,
 2                                        DisplayMetrics metrics)
 3     {
 4         switch (unit) {
 5         case COMPLEX_UNIT_PX:
 6             return value;
 7         case COMPLEX_UNIT_DIP:
 8             return value * metrics.density;
 9         case COMPLEX_UNIT_SP:
10             return value * metrics.scaledDensity;
11         case COMPLEX_UNIT_PT:
12             return value * metrics.xdpi * (1.0f/72);
13         case COMPLEX_UNIT_IN:
14             return value * metrics.xdpi;
15         case COMPLEX_UNIT_MM:
16             return value * metrics.xdpi * (1.0f/25.4f);
17         }
18         return 0;
19     }

其中單位為dip的,將其轉化為密度*值,也就是像素值,而單位sp的也將其轉化為px值,因此該方法可以能進行

dip-->px

sp-- >px

因此上面

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics );
這個方法肯定不能將sp轉化為dp,我們判斷

dp2sp(50) = 150

sp2dp(50) = 150

convertDipOrPx(50) = 150

convertPxOrDip(50) = 17
將代碼運行實際結果與判斷結果一致。

接下來我們繼續分析

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics );
該方法系統本意是用來做什么的?

查看官方說明:

Converts an unpacked complex data value holding a dimension to its final floating point value.

這里就把對應的值轉化為實際屏幕上的點值,也就是像素值。
如果是TypedValue.COMPLEX_UNIT_DIP,則乘以顯示密度density。

而如果是TypedValue.COMPLEX_UNIT_SP,則乘以像素密度scaledDensity

 

我們繼續刨根追底

density和scaledDensity的區別在於

density:The logical density of the display.顯示密度density = dpi/160

scaledDensity:A scaling factor for fonts displayed on the display.顯示字體的縮放因子 = density

實際上兩者的值一樣,為了驗證這個結論我們隨便找兩台機器小米2S和華為p7,取出density和scaledDensity是一致的,P7為3.0,小米2S = 2.0

 

因此本文結論轉化dp-px,px-dp,sp-px,px-sp

使用下面方法:

 1 //轉換dip為px 
 2   public static int convertDipOrPx(Context context, int dip) { 
 3       float scale = context.getResources().getDisplayMetrics().density; 
 4       return (int)(dip*scale + 0.5f*(dip>=0?1:-1)); 
 5   } 
 6    
 7   //轉換px為dip 
 8   public static int convertPxOrDip(Context context, int px) { 
 9       float scale = context.getResources().getDisplayMetrics().density; 
10      return (int)(px/scale + 0.5f*(px>=0?1:-1)); 
11  } 
12  
13   public static int sp2px(Context context, float spValue) {
14         float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
15         return (int) (spValue * fontScale + 0.5f);
16     }
17 
18     public static int px2sp(Context context, float pxValue) {
19         float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
20         return (int) (pxValue / fontScale + 0.5f);
21     }

 

如有錯誤,敬請指正。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM