更改语言环境:强制活动重新加载资源?

31

我在我的应用程序中有一个语言设置。当语言切换时,我希望所有的文本视图等立即更改语言。目前,我只是在配置文件中更改区域设置,所以当用户重新启动活动时,语言已经改变。

一个丑陋的解决方案是每次语言更改时让每个文本视图加载新资源。是否有更好的解决方案?也许有一种优雅的方式来离散地重新启动活动?或者只是强制重新加载资源?

6个回答

19

1
onConfigurationChanged() 应该在语言更改时触发。实际上,回头看一下,你的问题中有一个红旗,我第一次错过了,“我的应用程序中有一个语言设置”。这是否意味着您没有使用 Android 设备范围内的语言设置设施? - Jim Blackler
3
用户很烦人吧?我常常觉得没有用户我们会更好 :-) 无论如何,如果你已经自己开发了语言选择器,为什么刷新布局会有困难呢? - Jim Blackler
3
我不明白如何刷新视图。我将本地语言存储在共享首选项中,并在onConfigurationChanged中加载它,但在选择新的本地语言后没有任何刷新。 - emeraldhieu
7
你的意思是“在这里刷新你的视图”是什么?这是否会自动使用语言资源文件进行刷新,还是我需要手动为每个视图进行刷新? - IgorGanapolsky
1
如果没有收到 onConfigurationChanged 回调,请在 XML 中使用 android:configChanges="locale|layoutDirection"。 - Hradesh Kumar
显示剩余5条评论

11

我认为问题是在应用运行时切换语言并在UI中显示本地化消息。 android:configChanges="locale" 在设备设置中更改系统语言环境时(应用正在运行),调用 onConfigurationChanged 函数,但如果您想要在应用程序代码中更改语言环境,则不会调用该函数,因此界面不会更新。


7

以下是我在每个活动的onCreate()或onResume()方法中使用的方法(根据我的需求,如果我的活动将在用户更改语言设置后恢复,或者始终已经设置了语言):

然后我只需手动刷新视图,或从onConfigurationChanged()中刷新视图,该方法在此方法完成后调用。

public static void changeLocale(Activity activity, String language)
{
    final Resources res = activity.getResources();
    final Configuration conf = res.getConfiguration();
    if (language == null || language.length() == 0)
    {
        conf.locale = Locale.getDefault();
    }
    else
    {
        final int idx = language.indexOf('-');
        if (idx != -1)
        {
            final String[] split = language.split("-");
            conf.locale = new Locale(split[0], split[1].substring(1));
        }
        else
        {
            conf.locale = new Locale(language);
        }
    }

    res.updateConfiguration(conf, null);
}

伟大的思维。一种方法适用于所有活动。 - SMR
1
如果您在Fragment中执行此操作,该如何刷新本地化语言呢? - IgorGanapolsky
完美的答案,谢谢 @3c71 - Nicks
弃用的 请参见android.content.Context.createConfigurationContext(Configuration)。 - loshkin

0

假设您是通过类似以下方式更改语言的

private void updateLocale(@NonNull final Context context,
                          @NonNull final Locale newLocale) {
    final Resources resources = context.getResources();
    final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
    final Configuration configuration = resources.getConfiguration();
    configuration.locale = newLocale;
    resources.updateConfiguration(configuration, displayMetrics);
    Locale.setDefault(newLocale);
}

您需要在所有当前打开的活动中调用Activity.recreate(),这就是当用户在您没有订阅android:configChanges="locale"时更改系统语言会发生的情况。


2
非常感谢您能解释一下为什么要给我点踩。 - Thorbear
我正在使用这种方式来切换应用程序语言。但当系统语言为“英语”时,该应用程序无法加载我的“vi”资源。你知道为什么吗? - Nguyen
@Nguyen,“vi”代表“美属维尔京群岛”吗?根据Android Studio的设置,该地区的正确语言环境应为‘en-rVI’。 你的资源文件保存在哪里?为了使应用程序能够加载这些资源文件,你需要将语言环境设置为'en-rVI', 而不仅仅是‘en’,否则它将只加载普通的‘en’资源或默认资源。 - Thorbear

0
public void settingLocale(Context context, String language) {

Locale locale;

Configuration config = new Configuration();

 if(language.equals(LANGUAGE_ENGLISH)) {

    locale = new Locale("en");

    Locale.setDefault(locale);

    config.locale = locale;

}else if(language.equals(LANGUAGE_ARABIC)){

    locale = new Locale("hi");

    Locale.setDefault(locale);

    config.locale = locale;

}

context.getResources().updateConfiguration(config, null);

// Here again set the text on view to reflect locale change

// and it will pick resource from new locale

tv1.setText(R.string.one); //tv1 is textview in my activity

}

已弃用。请使用context.createConfigurationContext(Configuration)。 - loshkin

0
我不确定为什么onConfigurationChanged()不能被检测到。
嘿,sandis,你的意思是当你更改语言时onConfigurationChanged()方法没有在你的活动中调用?我也遇到了同样的问题。问题可能是这样的:当我们更改语言时,活动将进入onDestroy()(你可以试试),因此没有人可以调用onConfigurationChanged()。当我们再次启动活动时,将调用onCreate()而不是onConfigurationChanged()。在本地更改和方向更改中可能有所不同。

1
非常抱歉,这是我的错误:我的活动是选项卡活动的嵌入式活动,当在选项卡活动中添加android:configChanges="locale"时,它可以正常工作,当更改语言时,它不会进入onDestroy(),并且将在选项卡活动中调用onConfigurationChanged(),但是此方法无法在嵌入式活动中调用。 - himalayagiant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接