如何防止系统字体大小更改效果到Android应用程序?

jam*_*mes 37 android android-fonts

我最近完成了我的Android应用程序开发.我对所有textSize使用了sp(Scaled pixels).问题是当我调整系统字体大小时,我的应用程序的字体大小正在改变.我可以使用dp(设备无关像素),但维护我的应用程序需要很长时间.

我从引用的文字大小.

有没有办法防止系统字体大小更改效果到我的应用程序?

Ada*_*m S 44

如果您要求文本保持相同的大小,则必须使用dp.

引用文档:

An sp是相同的基本单位,但是按用户的首选文本大小(它是与比例无关的像素)进行缩放,因此在定义文本大小时(但从不用于布局大小)应使用此度量单位.

强调我的.

因此,您将看到sp用作文本大小单位的预期行为.

我不明白你使用dp花了太长时间来维护你的应用程序是什么意思 - 据我所知,这将是完全相同的努力量?(也许更少,但它可能会使眼睛不好的用户不太可用)

  • 如果您有一个正在运行的应用程序,将所有“sp”值切换为“dp”值很容易出错,并且需要更多时间来执行此操作。然后,如果选择切换回再次支持它,则需要恢复所有这些更改。在父活动中覆盖“fontScale”更有意义。这比改变资源需要更少的努力。它的可维护性也更好。下面的答案是覆盖“Context”的方法。 (3认同)
  • 尽管您的用法可能非常具体并且需要恒定的字体大小,但我建议您考虑如何在布局中容纳变化的字体大小,而不仅仅是完全避免使用。它将为您的用户带来更好的体验。 (2认同)

wel*_*k91 43

我最近也遇到了这个问题.我们的用户界面在屏幕尺寸有限的手机上无法很好地扩展,并且在用户将其可访问性选项设置为"巨大"的情况下更改整个用户界面似乎很愚蠢.

我在StackOverflow上发现这个问题最有帮助.

我所做的是将下面的代码放在我的BaseActivity(我的所有活动扩展的Activity类)中

public void adjustFontScale(Configuration configuration) {
    if (configuration.fontScale > 1.30) {
        LogUtil.log(LogUtil.WARN, TAG, "fontScale=" + configuration.fontScale); //Custom Log class, you can use Log.w
        LogUtil.log(LogUtil.WARN, TAG, "font too big. scale down..."); //Custom Log class, you can use Log.w
        configuration.fontScale = (float) 1.30;
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.getDefaultDisplay().getMetrics(metrics);
        metrics.scaledDensity = configuration.fontScale * metrics.density;
        getBaseContext().getResources().updateConfiguration(configuration, metrics);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在我super.onCreate()喜欢 之后立即调用它

adjustFontScale(getResources().getConfiguration());
Run Code Online (Sandbox Code Playgroud)

此代码执行的操作是确定用户是否将"辅助功能设置"中的字体比例设置为大于1.30f(注释5上的1.30f为"大",但可能因设备之间的不同而有所不同).如果用户将其字体设置得太大("超大","巨大"......),我们只将应用程序缩放为"大".

这允许您的应用扩展到用户的偏好(在一定程度上),而不会扭曲您的UI.希望这会有助于其他人.祝你好运!

其他提示

如果您希望某些布局可以与您的字体一起缩放(例如... RelativeLayout用作背景的字体),您可以使用sp而不是经典dp设置它们的宽度/高度.当用户更改其字体大小时,布局将根据应用程序中的字体进行相应更改.不错的小技巧.

  • 这不适用于牛轧糖。直到棉花糖它工作正常。 (3认同)
  • @Tallboy好问题.我已经看到代码以两种方式获取窗口管理器(像我一样使用getSystemService调用并使用getWindowManager(),就像我链接到的示例一样).我只是测试了我的代码两种方式,它们都运行良好.我相信我读到某个地方getWindowManager返回一个只读的Window Manager对象,这可能是两个方法之间的关键区别,但对于这个例子,它并不重要. (2认同)

dio*_*sgg 9

在Android 8.1(API 27)上,以上答案均不适合我。有效的方法如下:将以下代码添加到您的活动中:

Kotlin代码:

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(newBase)
    val newOverride = Configuration(newBase?.resources?.configuration)
    newOverride.fontScale = 1.0f
    applyOverrideConfiguration(newOverride)
}
Run Code Online (Sandbox Code Playgroud)

Java代码:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
    final Configuration override = new Configuration(newBase.getResources().getConfiguration());
    override.fontScale = 1.0f;
    applyOverrideConfiguration(override);
}
Run Code Online (Sandbox Code Playgroud)

您无需更改自己的AndroidManifest.xml

  • 这是Android API > N的解决方案,未在N以下的设备上进行测试。 (2认同)

loc*_*ost 6

我们就是这样做的。在Application类中,像这样重写onConfigurationChanged()。如果您希望不同的活动具有不同的行为,请在“活动”中重写onConfigurationChanged()

不要忘了添加清单标记android:configChanges =“ fontScale”,因为您自己在更改此配置。

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // In some cases modifying newConfig leads to unexpected behavior,
    // so it's better to edit new instance.
    Configuration configuration = new Configuration(newConfig);
    SystemUtils.adjustFontScale(getApplicationContext(), configuration);
}
Run Code Online (Sandbox Code Playgroud)

在一些帮助程序类中,我们有AdjustFontScale()方法。

public static void adjustFontScale(Context context, Configuration configuration) {
    if (configuration.fontScale != 1) {
        configuration.fontScale = 1;
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        wm.getDefaultDisplay().getMetrics(metrics);
        metrics.scaledDensity = configuration.fontScale * metrics.density;
        context.getResources().updateConfiguration(configuration, metrics);
    }
}
Run Code Online (Sandbox Code Playgroud)

警告!这将完全忽略辅助功能字体缩放用户设置,并阻止您的App字体缩放!


Max*_*lin 5

这就是你在 2018 年的做法(Xamarin.Android/C# - 其他语言中的相同方法):

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle bundle)
    {
...
    }

    protected override void AttachBaseContext(Context @base)
    {
        var configuration = new Configuration(@base.Resources.Configuration);

        configuration.FontScale = 1f;
        var config =  Application.Context.CreateConfigurationContext(configuration);

        base.AttachBaseContext(config);
    }
}
Run Code Online (Sandbox Code Playgroud)

您所需要的只是覆盖活动的attachBaseContext方法并在那里更新配置。

getBaseContext().getResources().updateConfiguration()已被弃用,尽管此方法有很多示例。如果您在 IDE 警告之外使用此方法,您可能会发现应用程序的某些部分未缩放。