Android N - 在运行时更改语言环境
Android N - Change Locale in runtime
我有一个 android 应用程序,我想在其中添加一个简单的首选项屏幕,其中有一个选项可以在语言(英语和葡萄牙语)之间切换。我已经准备好适当的字符串资源文件。
如果我在系统首选项中更改 OS 的主要语言,并重新加载应用程序,它将使用该语言,但我希望能够通过首选项屏幕进行操作。
我在这里的其他问题中看到,这在以前的 Android 版本中更容易做到,但该代码现在已被弃用,所以我采用了在每个 [=32] 中覆盖 attachBaseContext 方法的方法=] 为了通过包装器重新创建上下文,我在其中加载了当前在首选项中选择的语言环境,如 post:
所示
public class TCPreferenceActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.headers_preference, target);
}
@Override
protected boolean isValidFragment(String fragmentName) {
return TCPreferenceFragment.class.getName().equals(fragmentName);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("lang")) {
recreate();
}
}
@Override
protected void attachBaseContext(Context newBase) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(newBase);
String lang = pref.getString("lang", null);
Locale locale = new Locale(lang);
Context context = TCContextWrapper.wrap(newBase, locale);
super.attachBaseContext(context);
}
}
据我了解,在更改首选项时,会调用 onSharedPreferenceChanged 方法。我在那里重新创建了 activity,以便可以使用新上下文重新启动它。
这是我的上下文包装器:
public class TCContextWrapper extends ContextWrapper {
public TCContextWrapper(Context base) {
super(base);
}
public static ContextWrapper wrap(Context context, Locale newLocale) {
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
if (android.os.Build.VERSION.SDK_INT >= 24) {
configuration.setLocale(newLocale);
LocaleList localeList = new LocaleList(newLocale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
context = context.createConfigurationContext(configuration);
} else if (android.os.Build.VERSION.SDK_INT >= 17) {
configuration.setLocale(newLocale);
context = context.createConfigurationContext(configuration);
} else {
configuration.locale = newLocale;
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
return new ContextWrapper(context);
}
}
调试我可以看到调用了 onChange 方法,重新创建了首选项 activity,调用了上下文包装器,在包装器中正确创建了新的语言环境值,但是 activity启动时我一直看到相同的默认字符串。
有什么想法吗?
Language
您为 Locale
对象设置的 @parameter 应该是
An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
* up to 8 characters in length.
根据文档。
因此,如果您正在使用其他东西,您将看不到更新的语言环境。
我有一个 android 应用程序,我想在其中添加一个简单的首选项屏幕,其中有一个选项可以在语言(英语和葡萄牙语)之间切换。我已经准备好适当的字符串资源文件。
如果我在系统首选项中更改 OS 的主要语言,并重新加载应用程序,它将使用该语言,但我希望能够通过首选项屏幕进行操作。
我在这里的其他问题中看到,这在以前的 Android 版本中更容易做到,但该代码现在已被弃用,所以我采用了在每个 [=32] 中覆盖 attachBaseContext 方法的方法=] 为了通过包装器重新创建上下文,我在其中加载了当前在首选项中选择的语言环境,如 post:
所示public class TCPreferenceActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.headers_preference, target);
}
@Override
protected boolean isValidFragment(String fragmentName) {
return TCPreferenceFragment.class.getName().equals(fragmentName);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("lang")) {
recreate();
}
}
@Override
protected void attachBaseContext(Context newBase) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(newBase);
String lang = pref.getString("lang", null);
Locale locale = new Locale(lang);
Context context = TCContextWrapper.wrap(newBase, locale);
super.attachBaseContext(context);
}
}
据我了解,在更改首选项时,会调用 onSharedPreferenceChanged 方法。我在那里重新创建了 activity,以便可以使用新上下文重新启动它。
这是我的上下文包装器:
public class TCContextWrapper extends ContextWrapper {
public TCContextWrapper(Context base) {
super(base);
}
public static ContextWrapper wrap(Context context, Locale newLocale) {
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
if (android.os.Build.VERSION.SDK_INT >= 24) {
configuration.setLocale(newLocale);
LocaleList localeList = new LocaleList(newLocale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
context = context.createConfigurationContext(configuration);
} else if (android.os.Build.VERSION.SDK_INT >= 17) {
configuration.setLocale(newLocale);
context = context.createConfigurationContext(configuration);
} else {
configuration.locale = newLocale;
res.updateConfiguration(configuration, res.getDisplayMetrics());
}
return new ContextWrapper(context);
}
}
调试我可以看到调用了 onChange 方法,重新创建了首选项 activity,调用了上下文包装器,在包装器中正确创建了新的语言环境值,但是 activity启动时我一直看到相同的默认字符串。
有什么想法吗?
Language
您为 Locale
对象设置的 @parameter 应该是
An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
* up to 8 characters in length.
根据文档。 因此,如果您正在使用其他东西,您将看不到更新的语言环境。