Android-禁用系统字体缩放

设计师辛辛苦苦做出设计稿,开发人员辛辛苦苦把UI调好了,但是在Android用户修改系统的默认字体大小,原先的设计很容易失效,变得非常难看,考虑你的用户人群,又不想因为用户变更默认字体大小导致app的样式走样,我们可以这么做:

1.字体使用dp/dip代替sp

dp/dip(device independent pixels):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp=1px。不同设备有不同的显示效果,这个和设备硬件有关。
sp(Scaled Pixels):主要用于字体显示,与刻度无关的一种像素,与dp类似,但是可以根据用户的字体大小首选项进行缩放。

查看TextView的源码可以发现:

/**
* Set the default text size to the given value, interpreted as "scaled
* pixel" units.  This size is adjusted based on the current density and
* user font size preference.
*
* @param size The scaled pixel size.
*
* @attr ref android.R.styleable#TextView_textSize
*/
@android.view.RemotableViewMethod
public void setTextSize(float size) {
    setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
/**
* Set the default text size to a given unit and value.  See {@link
* TypedValue} for the possible dimension units.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
*
* @attr ref android.R.styleable#TextView_textSize
*/
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()));
}
private void setRawTextSize(float size) {
    if (size != mTextPaint.getTextSize()) {
        mTextPaint.setTextSize(size);
        if (mLayout != null) {
            nullLayouts();
            requestLayout();
            invalidate();
        }
    }
}

TypedValue.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;
}

dp与sp的换算差别只在于metrics.density和metrics.scaledDensity,

/**
* A scaling factor for fonts displayed on the display.  This is the same
* as {@link #density}, except that it may be adjusted in smaller
* increments at runtime based on a user preference for the font size.
*/
public float scaledDensity;

因此,sp和dp的区别是乘以一个scale。

2.通过重写系统方法禁用

在Application重写以下方法即可


@Override
public void onConfigurationChanged(Configuration newConfig) {
    if (newConfig.fontScale != 1)//非默认值
        getResources();
    super.onConfigurationChanged(newConfig);
}
@Override
public Resources getResources() {
    Resources res = super.getResources();
    if (res.getConfiguration().fontScale != 1) {//非默认值
        Configuration newConfig = new Configuration();
        newConfig.setToDefaults();//设置默认
        res.updateConfiguration(newConfig, res.getDisplayMetrics());
    }
    return res;
}

通过重写方法,把fontScale重置为默认值。此方式无侵入,仅对当前App有效。
可结合 一种极低成本的Android屏幕适配方式来看

欢迎爱学习的小伙伴加群一起进步:230274309 。 一起分享,一起进步!少划水,多晒干货!!欢迎大家!!!(进群潜水者勿加)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章