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 。 一起分享,一起進步!少划水,多曬乾貨!!歡迎大家!!!(進羣潛水者勿加)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章