版權宣告:
本賬號釋出文章均來自公眾號,承香墨影(cxmyDev),版權歸承香墨影所有。
每週會統一更新到這裡,如果喜歡,可關注公眾號獲取最新文章。
未經允許,不得轉載。
一、設定字型,該用 sp 還是 dp
對於 Android 開發而言,在開始學習的階段,就已經被告知,為了達到更好的 UI 適配,應該使用和畫素(px)的無關的一些相對尺寸來進行佈局。
- View 的尺寸和距離,使用 dp 為單位。
- 字型的大小,使用 sp 為單位。
雖然官方推薦使用 sp 為單位設定字型的尺寸,但是如果你依然堅定的使用 dp 來設定字型的尺寸,常規情況下,你會發現其實它們並沒有什麼區別。
寫個 Demo 來驗證一下,佈局程式碼如下:
這裡分別用了兩個 TextView,並分別使用 dp 和 sp 設定了它的尺寸,最後跟隨一個 View,它的尺寸和 TextView 的字型同大,來做一個標記。
可以看到,它們的文字是等大的,並且一箇中文的寬度,正好是藍色的 View 的寬度。
看樣子,sp 和 dp 在顯示上完全是沒有區別的。
而當我們在設定頁面,設定了字型的大小之後,這一切就不一樣了。
這裡,將字型調到最大,再來看看剛才 Demo 的顯示效果。
能明顯看到,使用 sp 為單位設定的字型,已經被變大了,而使用 dp 為單位設定的字型,依然保持原樣的尺寸。
由此,可以簡單的得出結論:
使用 sp 為單位標記字型,會隨著系統的字型大小而改變。而使用 dp 則不會。
而這種設定你也可以在官方文件中找到對應的描述。
大概的意思,就是說 sp 除了受到 density(螢幕密度) 的影響之外,還受到使用者設定的字型大小影響,所以一般推薦使用 sp 來設定字型,讓字型的顯示效果交給使用者設定。
有興趣可以看看文件:
developer.android.com/guide/topic…
既然已經有這樣的結論了,那麼就可以清晰認識到:
推薦使用 sp 來作為字型單位,但是如果有需要字型尺寸不跟隨系統字型尺寸變動,則可以使用 dp 來作為字型單位。
二、sp 到底是怎麼被改變的
到這裡就已經瞭解清楚 sp 和 dp 的區別了,但是我們應該不滿足於此,接下來再來研究一下,sp 是在何時被改變的吧。
一切的答案都在原始碼裡。
先從設定文字大小的入口,看看 TextView.setTextSize()
方法。
setTextSize()
是有兩個過載方法的,如果不設定 TypedValue 的話,它會預設認為你設定的是一個 TypedValue.COMPLEX_UNIT_SP
值,表示以 sp 為單位。
這裡最終會使用 TypedValue.applyDimension()
方法,計算出一個值,傳遞給 setRawTextSize()
方法,在本文中 applyDimension()
方法是如何計算尺寸的。
當 unit 為 COMPLEX_UNIT_SP 的使用,是使用 DisplayMetrics.scaledDensity
為一個比例,參與計算的。
接下來,我們的重點就是找到是什麼決定 scaleDensity 的值,看看 scaleDensity。
這裡的註釋也說明了,scaleDensity 不僅僅受裝置的 density 影響,還受使用者設定的字型尺寸影響。
DisplayMetrics.scaleDensity 在 DisplayMetrics 類中,並沒有初始化的地方,可它是一個 public 的欄位,也就是說可以被外部賦值初始化。
真正為 DisplayMetrics 中,各個欄位賦值的地方,在 ResourcesImpl 中,有一個 updateConfiguration()
方法,在其中,就有對 scaleDensity 進行初始化的邏輯。
可以看到,這裡又引入了一個新的計算因子,fontScale。而從 Configuration 的原始碼又瞭解到,fontScale 預設值為 1 ,這也就是為什麼通常情況下,density 和 scaleDensity 的值是相等的,它們分別影響了 dp 和 sp 最終渲染出來的畫素尺寸。
在 Display.java 的原始碼中,可以找到修改 fontScale 的過程。
正常情況下,會有三種不同的比例,0.75f、1.25f、1.0f ,而這裡的取值範圍,完全是廠商決定的,就像在本文開頭距離的裝置截圖中,可以看到有四個選項。
fontScale 被作為了一個系統的設定項,被儲存起來,使用 Settings.System
來進行管理,它的 Key 是 Setting.System.FONT_SCALE
。
而 FONT_SCALE 最終是由 ActivityManagerService 來負責取出,並且賦值到 Configuration 中的。
三、獲取使用者字型的改變
到這裡,本文的所有內容,就形成了閉環,瞭解清楚 sp 尺寸的來龍去脈。
而在開發過程中,如果想要知道當前環境下,使用者是否改變過字型大小,可以直接從 Configuration 中獲取即可。
只要不為 1 ,就是表示使用者有改變。
點贊或者分享吧~