版權聲明:html
本帳號發佈文章均來自公衆號,承香墨影(cxmyDev),版權歸承香墨影全部。java
每週會統一更新到這裏,若是喜歡,可關注公衆號獲取最新文章。android
未經容許,不得轉載。app
對於 Android 開發而言,在開始學習的階段,就已經被告知,爲了達到更好的 UI 適配,應該使用和像素(px)的無關的一些相對尺寸來進行佈局。ide
雖然官方推薦使用 sp 爲單位設定字體的尺寸,可是若是你依然堅決的使用 dp 來設置字體的尺寸,常規狀況下,你會發現其實它們並無什麼區別。佈局
寫個 Demo 來驗證一下,佈局代碼以下:學習
這裏分別用了兩個 TextView,並分別使用 dp 和 sp 設定了它的尺寸,最後跟隨一個 View,它的尺寸和 TextView 的字體同大,來作一個標記。字體
能夠看到,它們的文字是等大的,而且一箇中文的寬度,正好是藍色的 View 的寬度。ui
看樣子,sp 和 dp 在顯示上徹底是沒有區別的。3d
而當咱們在設置頁面,設置了字體的大小以後,這一切就不同了。
這裏,將字體調到最大,再來看看剛纔 Demo 的顯示效果。
能明顯看到,使用 sp 爲單位設定的字體,已經被變大了,而使用 dp 爲單位設定的字體,依然保持原樣的尺寸。
由此,能夠簡單的得出結論:
使用 sp 爲單位標記字體,會隨着系統的字體大小而改變。而使用 dp 則不會。
而這種設定你也能夠在官方文檔中找到對應的描述。
大概的意思,就是說 sp 除了受到 density(屏幕密度) 的影響以外,還受到用戶設定的字體大小影響,因此通常推薦使用 sp 來設定字體,讓字體的顯示效果交給用戶設定。
有興趣能夠看看文檔:
developer.android.com/guide/topic…
既然已經有這樣的結論了,那麼就能夠清晰認識到:
推薦使用 sp 來做爲字體單位,可是若是有須要字體尺寸不跟隨系統字體尺寸變更,則可使用 dp 來做爲字體單位。
到這裏就已經瞭解清楚 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 ,就是表示用戶有改變。
點贊或者分享吧~