Android:以新方式以编程方式设置语言环境会改变上下文
Android: Setting locale programmatically in the new way alters context
我知道有很多关于这个话题的讨论,我做了功课,之前阅读了很多 Whosebug 帖子,但其中 none 似乎解决了我的问题。
我有一个 setLocale 函数,它在每次 activity onCreate 时启动(不确定这是否是最好的方法,但我现在就是这样做的)和 setLocale 创建和 returns 一个应用了自定义语言环境配置的新上下文并且它可以工作(当您调用 getString 时,正确语言的文本是 return),但事实是这个新上下文(context = context.createConfigurationContext(config ) in setLocale) 是 ContextImpl? 类型,我期望它是 Activity 调用 setLocale,因为我然后 运行 方法需要一个 activity 在上下文中(activity 类型的上下文),但因为它是 ContextImpl,所以我得到 "Cannot cast android.app.ContextImpl to Activity"。清楚吗?有帮助吗?
谢谢。
public static Context setLocale(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources res = context.getResources();
Configuration config = new Configuration(res.getConfiguration());
if (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale);
context = context.createConfigurationContext(config);
} else {
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
编辑 1:一种好方法。
如果我在 SplashScreen 中插入下一段代码 activity:
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = getBaseContext().getResources().getConfiguration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
然后语言环境与整个应用一起工作,但我知道 UpdateConfiguration 已被弃用,我正在尝试使用可能是的新格式:
public static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources res = context.getResources();
Configuration config = new Configuration(res.getConfiguration());
if (Build.VERSION.SDK_INT <= 17) {
config.setLocale(locale);
context = context.createConfigurationContext(config);
} else {
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
但是第二次更新的方法不起作用,有什么建议吗?
经过长时间的调查,我会用我得出的结论来回答自己,这是以当前方式全局设置语言环境的最佳(和最新)解决方案。
我创建了一个 ContextWrapper class 如下:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Build;
import com.testmepracticetool.toeflsatactexamprep.helpers.TMLocale;
import java.util.Locale;
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
@SuppressWarnings("deprecation")
public static ContextWrapper wrap(Context context) {
String language = TMLocale.getLocale(context);
Configuration config = context.getResources().getConfiguration();
Locale sysLocale = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sysLocale = getSystemLocale(config);
} else {
sysLocale = getSystemLocaleLegacy(config);
}
if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(config, locale);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
context = context.createConfigurationContext(config);
} else {
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
return new MyContextWrapper(context);
}
@SuppressWarnings("deprecation")
public static Locale getSystemLocaleLegacy(Configuration config){
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Configuration config){
return config.getLocales().get(0);
}
@SuppressWarnings("deprecation")
public static void setSystemLocaleLegacy(Configuration config, Locale locale){
config.locale = locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale){
config.setLocale(locale);
}
}
此 class 将创建一个注入指定语言的上下文,稍后将使用以下方法作为上下文附加到当前 activity 中:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(MyContextWrapper.wrap(newBase));
}
这应该插入到每个 activity 但我最终做的是创建一个 BaseActivity class 并且每个 activity 扩展它.
通过这种方式,我们以最新和首选的方式设置了语言环境,并且它有效,当您执行 getString 时,会选择正确的语言。
希望我的调查能帮助遇到同样问题的其他人。
我知道有很多关于这个话题的讨论,我做了功课,之前阅读了很多 Whosebug 帖子,但其中 none 似乎解决了我的问题。
我有一个 setLocale 函数,它在每次 activity onCreate 时启动(不确定这是否是最好的方法,但我现在就是这样做的)和 setLocale 创建和 returns 一个应用了自定义语言环境配置的新上下文并且它可以工作(当您调用 getString 时,正确语言的文本是 return),但事实是这个新上下文(context = context.createConfigurationContext(config ) in setLocale) 是 ContextImpl? 类型,我期望它是 Activity 调用 setLocale,因为我然后 运行 方法需要一个 activity 在上下文中(activity 类型的上下文),但因为它是 ContextImpl,所以我得到 "Cannot cast android.app.ContextImpl to Activity"。清楚吗?有帮助吗?
谢谢。
public static Context setLocale(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources res = context.getResources();
Configuration config = new Configuration(res.getConfiguration());
if (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale);
context = context.createConfigurationContext(config);
} else {
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
编辑 1:一种好方法。
如果我在 SplashScreen 中插入下一段代码 activity:
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = getBaseContext().getResources().getConfiguration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
然后语言环境与整个应用一起工作,但我知道 UpdateConfiguration 已被弃用,我正在尝试使用可能是的新格式:
public static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources res = context.getResources();
Configuration config = new Configuration(res.getConfiguration());
if (Build.VERSION.SDK_INT <= 17) {
config.setLocale(locale);
context = context.createConfigurationContext(config);
} else {
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
}
return context;
}
但是第二次更新的方法不起作用,有什么建议吗?
经过长时间的调查,我会用我得出的结论来回答自己,这是以当前方式全局设置语言环境的最佳(和最新)解决方案。
我创建了一个 ContextWrapper class 如下:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Build;
import com.testmepracticetool.toeflsatactexamprep.helpers.TMLocale;
import java.util.Locale;
public class MyContextWrapper extends ContextWrapper {
public MyContextWrapper(Context base) {
super(base);
}
@SuppressWarnings("deprecation")
public static ContextWrapper wrap(Context context) {
String language = TMLocale.getLocale(context);
Configuration config = context.getResources().getConfiguration();
Locale sysLocale = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sysLocale = getSystemLocale(config);
} else {
sysLocale = getSystemLocaleLegacy(config);
}
if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setSystemLocale(config, locale);
} else {
setSystemLocaleLegacy(config, locale);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
context = context.createConfigurationContext(config);
} else {
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
return new MyContextWrapper(context);
}
@SuppressWarnings("deprecation")
public static Locale getSystemLocaleLegacy(Configuration config){
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static Locale getSystemLocale(Configuration config){
return config.getLocales().get(0);
}
@SuppressWarnings("deprecation")
public static void setSystemLocaleLegacy(Configuration config, Locale locale){
config.locale = locale;
}
@TargetApi(Build.VERSION_CODES.N)
public static void setSystemLocale(Configuration config, Locale locale){
config.setLocale(locale);
}
}
此 class 将创建一个注入指定语言的上下文,稍后将使用以下方法作为上下文附加到当前 activity 中:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(MyContextWrapper.wrap(newBase));
}
这应该插入到每个 activity 但我最终做的是创建一个 BaseActivity class 并且每个 activity 扩展它.
通过这种方式,我们以最新和首选的方式设置了语言环境,并且它有效,当您执行 getString 时,会选择正确的语言。
希望我的调查能帮助遇到同样问题的其他人。