以编程方式更改应用程序的语言而不刷新整个应用程序

时间:2018-03-20 09:44:21

标签: android locale multilingual

我试图根据用户的输入更改应用程序的语言。我尝试使用此代码来更改应用程序的语言,并且它的工作非常好。

public void setLocale(String lang) {
    myLocale = new Locale(lang);
    Resources res = getResources();
    DisplayMetrics dm = res.getDisplayMetrics();
    Configuration conf = res.getConfiguration();
    conf.locale = myLocale;
    res.updateConfiguration(conf, dm);
    Intent refresh = new Intent(MainActivity.this, MainActivity.class);
    startActivity(refresh);
}

但问题是app必须重新启动/刷新才能重新加载资源。

  • 这是以编程方式设置应用语言的正确方法吗?
  • 还有其他方法可以在不刷新应用的情况下更改语言吗?

3 个答案:

答案 0 :(得分:1)

是的,您的代码是正确的,如果您需要而不刷新应用程序

然后在应用课程中,您需要在onCreate()方法中调用此方法

String languageSelected = "en";//selected language
Locale myLocale = new Locale(languageSelected);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
getActivity().onConfigurationChanged(conf);//Call this method

您需要执行此特定语言才能在Application类中选择。

答案 1 :(得分:1)

尝试在您的活动中使用recreate()。这种方法在我的案例中是成功的。如果你在Fragment上,那么使用getActivity()。recreate();

SharedPreferences.Editor editor = prefs.edit();
                editor.putString(Constants.APP_STATE.SAVED_LOCALE, localeString);
                editor.apply();
                getActivity().recreate();

覆盖您的活动的以下方法:

@Override
protected void attachBaseContext(Context newBase) {
    SharedPreferences prefs = newBase.getSharedPreferences(Constants.APP_STATE.STATE_SHARED_PREFERENCES, MODE_PRIVATE);
    String localeString = prefs.getString(Constants.APP_STATE.SAVED_LOCALE, Constants.DEFAULTS.DEFAULT_LOCALE);
    Locale myLocale = new Locale(localeString);
    Locale.setDefault(myLocale);
    Configuration config = newBase.getResources().getConfiguration();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        config.setLocale(myLocale);
        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
            Context newContext = newBase.createConfigurationContext(config);
            super.attachBaseContext(newContext);
            return;
        }
    } else {
        config.locale = myLocale;
    }
    super.attachBaseContext(newBase);
    getResources().updateConfiguration(config, getResources().getDisplayMetrics());

当用户设置想要的语言环境时,您要做的是将其保存到SharedPreferences中的某个字符串中,并调用recreate()of activity。然后,这将调用attachBaseContext(Context context),在此方法中,将正确的语言环境设置为配置,然后将使用此配置创建新的上下文。之后,新的上下文将被发送到超级类,它将更新应用程序上下文并显示正确的语言环境。

这也很好,因为下次启动应用程序时会自动设置区域设置。

答案 2 :(得分:0)

更改区域设置是Configuration,这会导致您的活动重启。还有许多其他因素具有相同的效果,例如orientationkeyboardHidden。照顾你的活动状态。

  

如果重新启动活动,则需要恢复大量的活动   数据,重新建立网络连接或执行其他密集型操作   操作,然后由于配置更改可能会完全重启   用户体验缓慢。此外,你可能无法做到   使用系统的Bundle完全恢复您的活动状态   使用onSaveInstanceState()回调为您保存 - 它不是   旨在携带大型对象(如位图)和其中的数据   它必须序列化然后反序列化,这可能会消耗很多   内存并使配置变化缓慢。在这种情况下,   您可以减轻重新初始化部分活动的负担   通过在a重新启动活动时保留片段   配置改变。此片段可以包含对有状态的引用   你想要保留的对象。

不是最好的做法,但你可以处理它

<activity android:name=".MyActivity"
      android:configChanges="locale"
      android:label="@string/app_name">

然后在你的活动中

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Do your stuff here
}

记得照顾好你的州。使用setRetainFragment(true)是一种很好的方法。阅读this