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

Changing locale: Force activity to reload resources?

所以我在应用程序中有一种语言设置。 切换语言后,我希望所有的textviews等立即更改语言。 当前,我只是在配置中更改语言环境,因此用户重新启动活动时语言已更改。

解决我的问题的一个丑陋方法是,每次更改语言时,使每个textview加载新资源。 有更好的解决方案吗? 也许是一种巧妙地方法来离散地重新启动活动? 还是只是强制重新加载资源?


在您的AndroidManifest.xml中,将此属性添加到"活动"中

1
android:configChanges="locale"

在您的活动中覆盖onConfigurationChanged()

1
2
3
4
5
@Override
public void onConfigurationChanged(Configuration newConfig) {
  // refresh your views here
  super.onConfigurationChanged(newConfig);
}

https://developer.android.com/guide/topics/manifest/activity-element.html#config


我认为问题在于在应用程序的运行时切换语言并在UI中显示本地化消息。如果在应用程序运行时更改了系统区域设置(在设备的设置中),则android:configChanges="locale"调用onConfigurationChanged;如果您在应用程序的代码中更改了区域设置,则onConfigurationChanged会调用onConfigurationChanged。这就是为什么它不令人耳目一新。


这是我在每次活动onCreate()或onResume()期间根据需要使用的方法(如果我的活动将在用户更改语言设置后恢复,或者始终使用已设置的语言创建):

从那里,我只是手动刷新视图,或者从onConfigurationChanged()刷新视图,该方法完成后将被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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

}


I'm not sure why this isn't picked up by onConfigurationChanged().

嘿,桑迪斯,您是说您更改语言时未在活动中调用方法onConfigurationChanged()吗?我遇到了同样的问题。问题可能是这样的:当我们更改语言时,活动转到onDestroy()(您可以尝试这样做),因此没有人可以调用onConfigurationChanged()。当我们再次启动活动时,将调用onCreate(),而不是onConfigurationChanged()。区域更改和方向更改可能有所不同。


假设您正在通过以下方式更改语言

1
2
3
4
5
6
7
8
9
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"的情况下更改了系统语言,则会发生这种情况。