强制不同的区域设置仅适用于后堆栈中的顶级活动

ToV*_*ine 5 configuration android locale

我遇到了一个关于应用程序本地化的小问题:

情况是这样的 - 我为我的用户提供了始终使用挪威语应用程序的选项,无论系统语言如何。

它在大多数情况下都工作得很好(我进入设置,选中复选框以强制挪威语,按“后退”,之前的活动以挪威语显示 - 同样的“相反”),但是 - 仅语言发生变化似乎正确更新(重新加载资源)我的“后堆栈”中的第一个活动。

举例说明一个典型场景:

用户启动应用程序,并看到主要活动(英文)。从那里,他选择第二个活动(也是英语)。然后,他进入设置(从第二个活动的菜单中)并将偏好设置为强制挪威语。

然后,当他返回时,第二个活动会正确更新并以挪威语显示(到目前为止一切顺利)。然而,当他再次按“返回”返回主活动时,仍然以英文显示......

如果他返回并再次启动应用程序,主要活动将以挪威语正确显示......

这里有聪明人建议我应该做什么吗?

相关源码:

每个活动中包含的用于设置显示语言的代码:

在 onCreate 中:Globals.locale_default = Locale.getDefault().getDisplayLanguage();

public void onStart() {
    super.onStart();
    forceNorwegian = settings.getBoolean(getString(R.string.pref_key_forceNorwegian).toString(), false);
       if (forceNorwegian) {
           languageCheck("no");
       } else {
            Globals.locale = null;
            languageCheck(Globals.locale_default);
       }
}

public void languageCheck(String lang) {
    Globals.locale = new Locale( lang );
    // Check the current system locale and change it to Norwegian if it's not already the default
    Globals.checkLocale( this );
    if (Globals.language_changed) {
        // Restart activity
        Intent restart = getIntent();
        finish();
        Globals.language_changed = false;
        startActivity(restart);
    }
}
Run Code Online (Sandbox Code Playgroud)

全局.java:

public class Globals {

public static Locale locale = null;
    public static String locale_default = null;
    public static boolean language_changed = false;

    public static void checkLocale( Activity a ) {
        if( locale == null )
            return;

        Configuration config = a.getBaseContext().getResources().getConfiguration();
        if( !config.locale.equals( locale ) )
        {  // Change to the new locale.  Everything will need to be closed or reloaded.
            config.locale = locale;
            a.getBaseContext().getResources().updateConfiguration( config, null );
            language_changed = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

pau*_*ode 1

问题可能来自这样一个事实:布尔值 Globals.language_changed 是静态的,因此当从顶部活动调用 languageCheck 时,在从后面活动调用 languageCheck 之前,该布尔值将变为 false。您可以进行一些检查以查看层次结构中较早的 Activit 是否已打开,如果是,则将布尔值设置为 true,以防用户按下“后退”按钮。另一种选择是在选择新区域设置时立即重新加载所有打开的活动的逻辑。

--编辑-- 经过进一步检查,我认为这不完全是您的问题,因为您还在为每个活动更新 onStart 中的布尔值(当我第一次阅读它时,我错过了这部分)。也许当堆栈中较高的活动之一更改区域设置时,区域设置发生了更改,但堆栈中较低的活动只需要刷新。一项较低级活动的方向变化是否会将其从英语更改为挪威语?

--编辑 2 -- 检查这是否是问题的最简单方法是在 Globals.checkLocale 中添加一些日志记录以查看此条件语句是否为真:

if( !config.locale.equals( locale ) )
Run Code Online (Sandbox Code Playgroud)

如果这确实是问题所在,那么一种可能的解决方案是在每个活动中保存本地 Locale 实例而不是全局实例,并与该实例进行比较。例如,您可以在每个 Activity 的 onCreate 方法中获取一个 Locale 实例:

myLocale = getBaseContext().getResources().getConfiguration().locale;
Run Code Online (Sandbox Code Playgroud)

然后,不调用 Globals.checkLocal,只需执行以下条件语句(在每个 Activity 的 languageCheck 方法中):

if( Globals.locale != null && !Globals.locale.equals( myLocale ) )
{
    Configuration config = getBaseContext().getResources().getConfiguration();
    config.locale = Globals.locale;
    getBaseContext().getResources().updateConfiguration( config, null );
    Intent restart = getIntent();
    finish();
    startActivity( restart );
}
Run Code Online (Sandbox Code Playgroud)

重新启动后,将再次调用 Activity 的 onCreate 方法,这会将 myLocale 更新为正确的值。这只是一个快速解决方案,不一定是最好的解决方案。如果您愿意,您可以对此进行扩展,将部分代码移动到 Globals 中的方法中,或者使用与 onCreate 不同的位置来获取本地 Locale 实例每个活动。