我知道有关此主题的讨论很多,而且我已经完成了作业,并且以前阅读过许多stackoverflow帖子,但是似乎都没有解决我的问题的方法。

我有一个setLocale函数,它在每个活动onCreate上启动(不确定它是否是最好的方法,但是我现在正在这样做),并且setLocale创建并返回一个应用了自定义语言环境配置的新上下文,并且它可以正常工作(当您调用getString时,将以正确的语言返回文本),但是事实是这个新上下文(setLocale中的context = context.createConfigurationContext(config))是ContextImpl类型的吗?我希望它是称为setLocale的Activity,因为我随后在上下文(类型为activity的上下文)中运行需要活动的方法,但是由于它是ContextImpl,因此我得到"无法将android.app.ContextImpl转换为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活动中插入下一段代码:

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;

}

但是使用第二种更新方法后,它不起作用了,有什么建议吗?

"我希望它是名为setLocale的Activity" –嗯,不会。传递给createConfigurationContext()的Context包装在另一个Context中,特别是ContextImpl。"因为我然后在上下文中运行需要活动的方法(类型活动的上下文)" –您已经拥有Activity本身。不能只将它们用于那些方法吗?

为什么不在Application类中只设置一次语言环境?

好点@lionscribe,老实说我没有意识到,但是如果我认为在每个活动onCreate上设置语言环境是不明智的。虐待尝试您的建议,并让您知道。无论如何,我要提到的问题是context = context.createConfigurationContext(config);。更改上下文,创建ContextImpl类型的新对象仍将保持:s

谢谢您的宝贵时间,@ MikeM。您是对的,我可以使用活动本身来调用这些方法,但是由于我的应用程序是到目前为止设计的,所以我设置了每个活动的上下文类对象,并在需要的所有活动中使用它而且这些方法是沿着一些帮助程序类分布的,因此要塞满(识别)如此大量的方法调用将是困难且乏味的。

@MikeM。现在,使用此解决方案(在选择正确的语言文本时效果很好),问题是setLocale在创建活动的一开始就更改了我的上下文,因此每当我需要将该上下文转换为活动时,它都会引发异常。在Paso中,它运行良好,因为我以旧的方式使用setLocale,而没有context = context.createConfigurationContext(config);。

一旦在Application中设置了LocalLocal,就无需调用createConfigurationContext

谢谢@lionscribe。您为我指明了正确的方向,现在我在SplashScreen活动中更新了语言环境(在应用启动时仅被调用一次),而不是在每个活动中都在更新(废话),但是请查看我最近的编辑,因为我面临与此相关的一点问题,使用"旧样式"设置区域设置的方法,而不是当前更新的设置。

经过长时间的调查,我将回答自己的结论是,以目前的方式在全球范围内设置语言环境的最佳(最新)解决方案。

我创建了一个ContextWrapper类,如下所示:

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);

}

}

此类将使用指定的语言创建一个上下文,该语言随后将通过以下方法作为上下文附加到当前活动中:

@Override

protected void attachBaseContext(Context newBase) {

super.attachBaseContext(MyContextWrapper.wrap(newBase));

}

应该将其插入每个活动中,但是为了使其变得更简单和更好,我最终要做的是创建BaseActivity类,每个活动都对其进行扩展。

这样,我们以最新的首选方式设置语言环境,并且可以正常工作,当您执行getString时,会选择正确的语言。

希望我的调查可以帮助其他有相同问题的人。

嗨! 我使用了您的代码,但是我仍然遇到相同的问题。 我在BroadcastReceiver的onReceive事件中收到"无法将android.app.ContextImpl转换为Activity"。 知道为什么会这样吗?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐