Android: TextView 及其子類通過代碼和 XML 設置字體大小的存在差異的分析


原因: 在代碼中通過 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     }

 


免責聲明!

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



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