Android多语言适配的示例代码(兼容7.0+)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Android多语⾔适配的⽰例代码(兼容7.0+)
⼀、前⾔
1、安卓系统本⾝对多语⾔适配就提供了⼀套框架和API。

我们就直接⽤就可以了。

2、更换语⾔必须recreate Activity。

⽬前,没见过可以不重建的⽅法。

常⽤App,也都是重建的,可以看的到。

3、兼容性问题。

现在越来越多设备都是安卓7.0+新⼿机的安卓版本会更⾼(安卓8.0+),所以适配是必要的。

4、⽬前,⽹上⼤部分相关⽂章都是不兼容7.0+的,具体做法⼀搜⼀⼤把。

⼆、具体做法
1、多语⾔⽂件
⽂件夹命名参考下⾯博客(⽹上有很多):
value默认放英⽂的资源⽂件,简体中⽂⽂件夹命名为values-zh-rCN,不需要翻译的设置translatable如下:
复制代码代码如下:
<string name="app_name_english" translatable="false">You App English Name</string>
2、多语⾔⼯具类
public class LanguageUtils {
public static final String CHINESE_SIMPLE = "zh_CN";
public static final String ENGLISH = "en";
public static final String AUTO = "auto";
private static final String TAG = "LanguageUtils";
//public static final String[] LOCALES = Utils.getContext().getResources().getStringArray(R.array.locales);
private LanguageUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
public static void setSystemDefaultLocale(Locale locale) {
}
public static boolean isSetValue(Context context) {
Locale currentLocale = context.getResources().getConfiguration().locale;
return currentLocale.equals(getSetLocale());
}
private static Locale getSetLocale() {
String locale = SPUtils.getInstance(_APP_SETTINGS).getString(BaseConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO);
if (locale.equals(LanguageUtils.AUTO)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Resources.getSystem().getConfiguration().getLocales().get(0);//解决了获取系统默认错误的问题
} else {
return Locale.getDefault();
}
}
String[] array = locale.split("_");
String language = array[0];
if (array.length > 1) {
String country = array[1];
return new Locale(language, country);
}
return new Locale(language);
}
public static int getSetIndex() {
String languageSet = SPUtils.getInstance(_APP_SETTINGS).getString(BaseConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO); int localeIndex = 0;
switch (languageSet) {
case LanguageUtils.AUTO:
localeIndex = 0;
break;
case LanguageUtils.CHINESE_SIMPLE:
localeIndex = 1;
break;
case LanguageUtils.ENGLISH:
localeIndex = 2;
break;
}
return localeIndex;
}
public static Context wrapContext(Context context) {
Resources resources = context.getResources();
Locale locale = LanguageUtils.getSetLocale();
Configuration configuration = resources.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
configuration.setLocale(locale);
LocaleList localeList = new LocaleList(locale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
} else {
configuration.setLocale(locale);
}
return context.createConfigurationContext(configuration);
}
public static void applyChange(Context context) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
Locale locale = getSetLocale();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocale(locale);
LocaleList localeList = new LocaleList(locale);
LocaleList.setDefault(localeList);
conf.setLocales(localeList);
} else {
conf.setLocale(locale);
}
res.updateConfiguration(conf, dm);
}
}
3、代码分析&兼容7.0+
3.1、如何获取系统的语⾔设置,也就是7.0+你选择auto,可以正确切换。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Resources.getSystem().getConfiguration().getLocales().get(0);//解决了获取系统默认错误的问题
} else {
return Locale.getDefault();
}
看到这篇⽂章的你,可能已经看过⽹上很多其他相关的⽂章,应该知道,7.0+系统有个很奇怪的地⽅:
如果你在app内切换了语⾔(⽐如说是英⽂),且该语⾔和系统的设置(⽐如说是中⽂)不同,那么你再次切换语⾔并选择auto时,通过Locale.getDefault()获取会错误,或者你通过LocaleList.get(0)也是错误的,你之前选择的语⾔(英⽂)排序被提前了。

有些⽂章的解决⽅案是在app打开时持久化系统设置,这样你切换app的语⾔就不会影响你获取系统的设置,但这样没必要,太⿇烦(应该是不知道上⾯的⽅法)。

7.0+的系统设置也看的出差别,以前,设置系统语⾔直接选择就可以了,现在你要先添加,然后再排序,排在第⼀个的才是系统显⽰的语⾔!
3.2、写个BaseActivity作为所有Activity⽗类
新建⼀个BaseActivity⽤于继承,重写:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LanguageUtils.wrapContext(newBase));
}
然后在切换语⾔后,你要recreate Activity。

这个在哪调⽤就看具体需求了。

你可以像微信那样,清空栈,然后直接重启到主界⾯,也可以在设置界⾯recreate,但栈内其他Activity,也要想办法通知recreate。

3.3、屏蔽系统设置改变
如果app的语⾔选项不是auto,那么系统语⾔设置修改时,app就不应该跟着系统变,⽽是按照⾃⼰设置的语⾔显⽰。

写⼀个类继承于Application(注意要在manifest配置哦,不然⽆效的)
public class MyApp extends Application {
private Configuration deltaConfig;
@Override
public void onConfigurationChanged(Configuration newConfig) {
LogUtils.d(TAG, "调⽤了onConfigurationChanged");
int diff = newConfig.diff(deltaConfig);
String languageSet = SPUtils.getInstance(_APP_SETTINGS).getString(AppConstants.SP.KEY_LANGUAGE, LanguageUtils.AUTO); if (languageSet.equals(LanguageUtils.AUTO)) {//看app语⾔设置是不是auto,是的话不管,直接super
super.onConfigurationChanged(newConfig);
deltaConfig = newConfig;
} else if (diff != ActivityInfo.CONFIG_LOCALE) {//这个Configuration更改是不是语⾔,不是的话,也不管
super.onConfigurationChanged(newConfig);
deltaConfig = newConfig;
}
//这⾥使系统设置语⾔⽆效
//相当于省略了
//else{
// return;
//}
}
@Override
public void onCreate() {
super.onCreate();
//app打开时记录系统设置
deltaConfig = getApplicationContext().getResources().getConfiguration();
LanguageUtils.applyChange(getApplicationContext());
}
}
}
3.4、其他问题
Application的Context也要更新
LanguageUtils.applyChange(context);
LanguageUtils.applyChange(context.getApplicationContext());
但即使这样,还是有点问题,主要在于:
如果Activity的Title你是在manifest中定义的,如下label:
<activity
android:name=".ui.activity.AboutActivity"
android:launchMode="singleTop"
android:label="@string/lable_activity_about"
android:theme="@style/AppTheme.NoActionBar"/>
那么,即使你更新了ApplicationContext,有些Activity也有可能不⽣效,⽽且每次都还不⼀样,这个没法复现(很迷)。

不知道是不是系统bug(测试系统是⼀加3 氢OS 8.0),或者是有其他更好的写法?
针对这个问题,只要在activity oncreate() ⾥setTitle()就好了。

这样是不会有什么问题的。

以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

相关文档
最新文档