android改变整个app字体大小,Android系统字体大小如何影响app的字体大小?
在Android应用开发过程中,一定会碰到本来完美的布局,在系统字体大小设置【最大】时变成一团浆糊。解决办法网上也有很多,但是分析原理的却几乎没看到。博主在碰到问题的第一时间也是直接用了网上的方法,即在BaseActivity中重写getResources方法如下@Overridepublic Resources getResources() {Resources res = super.getR
在Android应用开发过程中,一定会碰到本来完美的布局,在系统字体大小设置【最大】时变成一团浆糊。解决办法网上也有很多,但是分析原理的却几乎没看到。博主在碰到问题的第一时间也是直接用了网上的方法,即在BaseActivity中重写getResources方法如下
@Override
public Resources getResources() {
Resources res = super.getResources();
Configuration config=new Configuration();
config.setToDefaults();
res.updateConfiguration(config,res.getDisplayMetrics());
return res;
}
这个方法是有效的。
但是作为开发人员必须懂得举一反三,而要举一反三就必须要“知其所以然”,于是博主就去探寻了一番,才有了此篇文章。
1.字体大小如何设置
这个简单,就拿TextView来说,设置字体大小调用setTextSize方法就行了。如果你直接以px为单位设置字体大小,那么应用字体大小是绝对不会被系统字体所影响的,但是绝大多数时候,我们用的单位都是sp,sp是什么?sp = scaled pixel 即缩放了的像素值。而如果用了sp就一定会受系统字体大小的影响。
我们拿TextView来举例,看看它的setTextSize方法
public void setTextSize(int unit, float size) {
Context c = getContext();
Resources r;
if (c == null)
r = Resources.getSystem();
else
r = c.getResources();
setRawTextSize(TypedValue.applyDimension(
unit, size, r.getDisplayMetrics()));
}
看一眼代码,至少可以确定一件事情:设置的字体大小在内部做了计算和变换。
没错,就是这个applyDimension方法干的好事!!
我们跟进去看看先:
public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP://看这里,看这里
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}
事实一目了然,我们设置进去的value值,这个方法返回的是value*metrics.scaledDensity 问题肯定出在scaledDensity这个属性身上!!!
好了,字体大小的设置到此结束。
2. scaledDensity真面目
根据网上提供的办法,我们知道字体大小的影响跟Resources有关(具体原因待分析)。于是博主在Resources.java源码中进行了查找,发现了一个重要的方法
public void updateConfiguration(Configuration config,
DisplayMetrics metrics) {
updateConfiguration(config, metrics, null);
}
然后是具体实现的方法:
public void updateConfiguration(Configuration config,
DisplayMetrics metrics, CompatibilityInfo compat) {
synchronized (mAccessLock) {
... 省略代码 ...
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
... 省略代码 ...
}
synchronized (sSync) {
if (mPluralRule != null) {
mPluralRule = NativePluralRules.forLocale(config.locale);
}
}
}
相信大家都看到了,mMetrics.scaledDensity的值其实是受mConfiguration.fontScale影响的。那么我们的研究对象又一次转变了,变成了fontScale。
此时,我们对照一下,网上的解决系统字体大小影响的代码片段
@Override
public Resources getResources() {
Resources res = super.getResources();
Configuration config=new Configuration();
config.setToDefaults();
res.updateConfiguration(config,res.getDisplayMetrics());
return res;
}
看来路子是走对了,这里也是对Configuration进行了设置,并且还调用了updateConfiguration方法。
并且我还告诉你,这里的config.setToDefaults()方法内部第一句代码就是fontScale=1。
那么分析到这里,我们基本可以推测:如果修改系统的字体大小,fontScale肯定会改变!
3. 最终解决
首先,推测是需要验证的。我们可以编写一个demo,在MainActivity的onCreate方法中打印fontScale值
Log.d("Javine","fontScale = "+getResources().getConfiguration().fontScale);
博主的是锤子T1,打印出来的结果是
标准 —– fontScale = 1.0
较大 —– fontScale = 1.1
最大 —– fontScale = 1.4
到此为止,我们还是不能百分之百确定问题一定是因为fontScale值的变化引起的。
我们还需要做最后一件事情——通过修改fontScale值来修复字体大小的问题!
跟网上的解决办法一样,重载Activity的getResources方法如下:
@Override
public Resources getResources() {
//获取到resources对象
Resources res = super.getResources();
//修改configuration的fontScale属性
res.getConfiguration().fontScale = 1;
//将修改后的值更新到metrics.scaledDensity属性上
res.updateConfiguration(null,null);
return res;
}
经博主测试,问题完美解决!!并且,对比网上的解决办法,我们并没有新建一个Configuration对象,从性能角度上说,这个办法更优。
更多推荐
所有评论(0)