当你在设置里修改字体大小的时候,到底在修改什么

版权声明:html

本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。java

每周会统一更新到这里,若是喜欢,可关注公众号获取最新文章。android

未经容许,不得转载。app

1、设定字体,该用 sp 仍是 dp

对于 Android 开发而言,在开始学习的阶段,就已经被告知,为了达到更好的 UI 适配,应该使用和像素(px)的无关的一些相对尺寸来进行布局。ide

  • View 的尺寸和距离,使用 dp 为单位。
  • 字体的大小,使用 sp 为单位。

虽然官方推荐使用 sp 为单位设定字体的尺寸,可是若是你依然坚决的使用 dp 来设置字体的尺寸,常规状况下,你会发现其实它们并无什么区别。布局

写个 Demo 来验证一下,布局代码以下:学习

/sp-xml.png
/sp-xml.png

这里分别用了两个 TextView,并分别使用 dp 和 sp 设定了它的尺寸,最后跟随一个 View,它的尺寸和 TextView 的字体同大,来作一个标记。字体

/sp-demorun.png
/sp-demorun.png

能够看到,它们的文字是等大的,而且一个中文的宽度,正好是蓝色的 View 的宽度。ui

看样子,sp 和 dp 在显示上彻底是没有区别的。3d

而当咱们在设置页面,设置了字体的大小以后,这一切就不同了。

/sp-setting.png
/sp-setting.png

这里,将字体调到最大,再来看看刚才 Demo 的显示效果。

/sp-demorun2.png
/sp-demorun2.png

能明显看到,使用 sp 为单位设定的字体,已经被变大了,而使用 dp 为单位设定的字体,依然保持原样的尺寸。

由此,能够简单的得出结论:

使用 sp 为单位标记字体,会随着系统的字体大小而改变。而使用 dp 则不会。

而这种设定你也能够在官方文档中找到对应的描述。

/sp-doc.png
/sp-doc.png

大概的意思,就是说 sp 除了受到 density(屏幕密度) 的影响以外,还受到用户设定的字体大小影响,因此通常推荐使用 sp 来设定字体,让字体的显示效果交给用户设定。

有兴趣能够看看文档:

developer.android.com/guide/topic…

既然已经有这样的结论了,那么就能够清晰认识到:

推荐使用 sp 来做为字体单位,可是若是有须要字体尺寸不跟随系统字体尺寸变更,则可使用 dp 来做为字体单位。

2、sp 究竟是怎么被改变的

到这里就已经了解清楚 sp 和 dp 的区别了,可是咱们应该不知足于此,接下来再来研究一下,sp 是在什么时候被改变的吧。

一切的答案都在源码里。

先从设定文字大小的入口,看看 TextView.setTextSize() 方法。

/sp-settextsize.png
/sp-settextsize.png

setTextSize() 是有两个重载方法的,若是不设定 TypedValue 的话,它会默认认为你设定的是一个 TypedValue.COMPLEX_UNIT_SP 值,表示以 sp 为单位。

这里最终会使用 TypedValue.applyDimension() 方法,计算出一个值,传递给 setRawTextSize() 方法,在本文中 applyDimension() 方法是如何计算尺寸的。

/sp-dims.png
/sp-dims.png

当 unit 为 COMPLEX_UNIT_SP 的使用,是使用 DisplayMetrics.scaledDensity 为一个比例,参与计算的。

接下来,咱们的重点就是找到是什么决定 scaleDensity 的值,看看 scaleDensity。

/sp-scaledensity.png
/sp-scaledensity.png

这里的注释也说明了,scaleDensity 不只仅受设备的 density 影响,还受用户设定的字体尺寸影响。

DisplayMetrics.scaleDensity 在 DisplayMetrics 类中,并无初始化的地方,可它是一个 public 的字段,也就是说能够被外部赋值初始化。

真正为 DisplayMetrics 中,各个字段赋值的地方,在 ResourcesImpl 中,有一个 updateConfiguration() 方法,在其中,就有对 scaleDensity 进行初始化的逻辑。

/sp-resource.png
/sp-resource.png

能够看到,这里又引入了一个新的计算因子,fontScale。而从 Configuration 的源码又了解到,fontScale 默认值为 1 ,这也就是为何一般状况下,density 和 scaleDensity 的值是相等的,它们分别影响了 dp 和 sp 最终渲染出来的像素尺寸。

在 Display.java 的源码中,能够找到修改 fontScale 的过程。

/sp-changescale.png
/sp-changescale.png

正常状况下,会有三种不一样的比例,0.75f、1.25f、1.0f ,而这里的取值范围,彻底是厂商决定的,就像在本文开头距离的设备截图中,能够看到有四个选项。

fontScale 被做为了一个系统的设置项,被存储起来,使用 Settings.System 来进行管理,它的 Key 是 Setting.System.FONT_SCALE

而 FONT_SCALE 最终是由 ActivityManagerService 来负责取出,而且赋值到 Configuration 中的。

/sp-as.png
/sp-as.png

3、获取用户字体的改变

到这里,本文的全部内容,就造成了闭环,了解清楚 sp 尺寸的前因后果。

而在开发过程当中,若是想要知道当前环境下,用户是否改变过字体大小,能够直接从 Configuration 中获取便可。

/sp-getfontscale.png
/sp-getfontscale.png

只要不为 1 ,就是表示用户有改变。

公众号二维码.jpg
公众号二维码.jpg

点赞或者分享吧~

相关文章
相关标签/搜索