两种方法避免Android系统更改字体大小

开阔视野。

Posted by YSY on October 20, 2018

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

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

@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以局部控制字体大小上限:

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,来达到我们的目的。