原因: 在代碼中通過 setTextSize(float size) 設置,使用的是 sp 為默認單位。 而 XML 中使用了 px,所以需要使用先把做好 sp 和 px 的轉換工作。
最近在做 app 內修改字體大小,同時在設置頁面有個預覽界面,這個時候需要通過代碼設置字體大小了
1 tv.setTextSize(getResources().getDimension(R.dimen.XLargeTextSize));
結果發現比通過 XML 設置的字體大小要大不少,看到了 setTextSize() 的源碼,發現了問題所在。
1. setTextSize(), 該方法調用的是 setTextSize(TypedValue.COMPLEX_UNIT_SP, size),看到了使用了一個尺寸單位 TypedValue.COMPLEX_UNIT_SP
1 @android.view.RemotableViewMethod 2 public void setTextSize(float size) { 3 setTextSize(TypedValue.COMPLEX_UNIT_SP, size); 4 }
跟進到 TypedValue 中,查看到常量,根據輸入不同的單位,解析不同的 size,然后確定文字大小
查看到有三個常量:(px, dip(dp), sp)
1 /** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */ 2 public static final int COMPLEX_UNIT_PX = 0; 3 /** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent 4 * Pixels. */ 5 public static final int COMPLEX_UNIT_DIP = 1; 6 /** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */ 7 public static final int COMPLEX_UNIT_SP = 2;
2. setTextSize(int unit, float size),在這個方法中,解析了 TypedValue 中的常量,解析方法為 applyDimension()
1 public void setTextSize(int unit, float size) { 2 Context c = getContext(); 3 Resources r; 4 5 if (c == null) 6 r = Resources.getSystem(); 7 else 8 r = c.getResources(); 9 10 setRawTextSize(TypedValue.applyDimension( 11 unit, size, r.getDisplayMetrics())); 12 }
3. TypedValue.applyDomension(),根據不同的單位,返回不同的 value。 1. 選擇 px 為單位,直接返回輸入的 value; 2. 選擇 dp 為單位 ,返回為 value * density;3. 選擇 sp 為單位,返回 value* scaledDensity
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 }
4. setRawTextSize(),這個方法中,調用了 mTextPaint.setTextSize(), mTextPaint 是 TextPaint 的實例, TextPaint 繼承 Paint,可以看到就是調用的 Paint 的 setTextSize() 方法。
1 private void setRawTextSize(float size) { 2 if (size != mTextPaint.getTextSize()) { 3 mTextPaint.setTextSize(size); 4 5 if (mLayout != null) { 6 nullLayouts(); 7 requestLayout(); 8 invalidate(); 9 } 10 } 11 }