多语言设置
项目中包含的语言有中文简体,中文繁体,英语,西班牙语,泰语,印尼语,葡萄牙语
一、核心API
1、获取到系统当前语言Locale:
public static Locale getAppLocale(Context context) {
//获取应用语言
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
Locale locale = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = configuration.getLocales().get(0);
} else {
locale = configuration.locale;
}
return locale;
}
2、更新Locale:(updateConfiguration)
public static void setConfiguration(Context context) {
Locale locale = LocaleIsHaveSaveLanguage(context);
Configuration configuration = context.getResources().getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLocale(locale);
} else {
configuration.locale = locale;
}
Resources resources = context.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
resources.updateConfiguration(configuration, dm);//语言更换生效的代码!
}
二、关键注意点(踩坑)
1、关于更新Local:
系统提供了两种方式,updateConfiguration和createConfigurationContext,我们采用的是第一种方案。第二种其实就是创建了一个Context的包装类,需要在Activity或者Application的attachBaseContext中进行拦截返回。该方法虽然是推荐的API,但是有很大的缺陷:
①.无法实时更新Locale,因为attachBaseContext方法只会在Activity或Application初始化的时候调用一次,之后无法调用。
②.更改了全局的Context,会导致一些三方库初始化的Context与实际应用的Context不一致,造成异常奔溃。
2、关于上下文:
Android更新应用内的Locale,是通过Context的resource更新的,而Application的resource和所有Activity的resource是不同的两个资源对象,也就是说所有Activity的resource共享一个对象(一份配置),Application的是单独的一份配置,这也就表示了我们使用这两种context获取或更新Locale时,会出现差异性:一个更新了一个没更新。 由于我们在获取Locale时,无法保证使用Application的Context还是Activity的Context,所以需要我们在更新Locale时,将两种Context都更新。
3、关于简体繁体
由于某种不知名原因,导致手机设置非中国地区而应用内选择简体中文时,应用的是中文繁体的配置,所以在这种情况下,我们需要做一下特殊处理:语言选择的是中文(zh),但是地区是非繁体(TW)、非中国(CN)的情况下,将地区强制设置为中国(CN):
if ((locale.getLanguage().equals(Constants.zh) && !locale.getCountry().equals(Constants.TW))
&& (!locale.getCountry().equals(Constants.CN))) {
locale = new Locale(locale.getLanguage(), Constants.CN);
}
4、关于WebView:
从结果上来说,由于系统对于WebView的改变,会导致第一次new WebView(context)时,Locale被重置:
1.创建WebView的context无论是Activity的context还是Application的context都会有问题
2.如果第一次创建WebView前,context使用updateConfiguration更新过Locale,则context对应的Locale会重置为变更之前的Locale
3.如果第一次创建WebView前,context使用createConfigurationContext更新过Locale,则conteext对应的Locale不会改变
虽然第3点可以看出createConfigurationContext方法好处,但是鉴于该方法无法避免它的劣势,还是不好用。
面对这种情况,我们可以在首次使用WebView后,再通过updateConfiguration方法设置一遍两个context的Locale即可。
项目中我们是在AppApplication初始化时初始化Webview并直接销毁它:
new WebView(mAppContext).destroy();