当用户更改系统的字体大小后,App界面可能会变得面目全非,适配起来非常困难。
有的时候我们可能不需要去适配,那么就需要限制部分页面或者控件受系统字体大小更改的影响。

目前,大家在网上搜,一般都是下面的这个办法,这也是今天介绍的第一个方法,可以直接使当前Activity的所有字体大小固定:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public Resources getResources() {
Resources resources = super.getResources();
if (resources != null) {
Configuration configuration = resources.getConfiguration();
// 系统设置的字体大小超过了我们接受的限制
if (configuration != null && configuration.fontScale > mLimitFontScale) {
configuration.fontScale = mLimitFontScale; // 强制设置为自己想要的放大倍数
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}
}
return resources;
}

这种方式主要是重写系统的getResources方法,来强制更新fontScale的值。但这个方法有个缺点,即会影响当前Activity所有字体,若我们只需要限制某个TextView的最大字体size,而不是全局,该怎么办呢?

第二种方法,自定义TextView以局部控制字体大小上限:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class LimitSizeTextView extends TextView {

private float mLimitFontScale = 0; // 若在TextView实例化时没有调用setLimitFontScale则默认值为0
private float mRealTextSize = 0;

public LimitSizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public void setLimitFontScale(float limitFontScale) {
this.mLimitFontScale = limitFontScale;
}

@Override
public void setText(CharSequence text, BufferType type) {
if (mLimitFontScale > 0 && !TextUtils.equals(text, getText())) {
super.setText(text, type);
// 若设置了最大字体尺寸,则强制改变size,避免系统超大字体等情况导致字体过大
float curFontScale = getResources().getConfiguration().fontScale;
if (curFontScale >= mLimitFontScale) {
if (mRealTextSize == 0) {
// 字体大小只修正一次
mRealTextSize = getTextSize() * (mLimitFontScale / curFontScale);
}
// 注意这里设置大小的单位是像素
setTextSize(TypedValue.COMPLEX_UNIT_PX, mRealTextSize);
}
} else {
super.setText(text, type);
}
}
}

其实思想和第一种方法类似,都是“劫持”一下系统API,来达到我们的目的。