安卓国际化(多语言切换),支持小语种
最近安卓开发遇到一个新的需求,需要支持多语言,而且还是我们五十六个大家庭中的藏语,一时间点懵了,毕竟从来没搞过多语言,一下来的还是比较小众的。后面研究了一番那个,还是大致搞出来了,这里简单写篇博客记一下。官方文档以前一有问题总喜欢在网上瞎找博客教程,后面发现很多写的很好的博文都是抄的官方文档,就把官方文档收藏了,有问题先看官方文档,下面是官方文档对多语言的教程:https://developer.
最近安卓开发遇到一个新的需求,需要支持多语言,而且还是我们五十六个大家庭中的藏语,一时间点懵了,毕竟从来没搞过多语言,一下来的还是比较小众的。后面研究了一番那个,还是大致搞出来了,这里简单写篇博客记一下。
官方文档
以前一有问题总喜欢在网上瞎找博客教程,后面发现很多写的很好的博文都是抄的官方文档,就把官方文档收藏了,有问题先看官方文档,下面是官方文档对多语言的教程:
https://developer.android.google.cn/training/basics/supporting-devices/languages
创建资源文件
实际上官方文档写的已经非常详细了,但是我还是想说点不一样的东西。我需要弄的是属于中国区域的藏语,可是找遍网上博文列出的支持语言也没找到藏文对应的代码,差点我就使用最笨的方法自己用代码控制语言切换了,下面看我怎么做的:
这里选中 value 资源目录,创建一个资源文件,就是我们另一份语言的资源文件了
这里从下方选中 locale 移到右边去,注意 Language 里面的小字哈
我们在 Language 里面输入 Tibetan,这时候这我们的藏语就出来了,实际找也能找到,我这里只是想说明安卓支持的语言并不仅仅是网上列举的那些。
这里我创建的是 strings.xml,也就是我们的字符串资源文件
使用字符串资源文件
还记得我们在代码和布局文件总直接使用字符串的警告吗?
一般来说我们可以使用下面代码抑制警告,如果你和我一样不能接受任何一个 warning 的话
@SuppressLint("SetTextI18n")
tools:ignore="HardcodedText"
但是这些警告是提示你直接使用字符串不适合国际化,我们需要使用多语言,就不应该忽视这些警告,而是应该尽量使用字符串资源文件去加载字符串,怎么使用应该不用说了。
修改应用语言设置
配置好不同资源后,应用如果不做任何修改的话,将会跟随系统的语言,可以自己试试。但是一般在应用总提供设置功能比较好,下面是在应用总设置语言的代码:
Resources resources = context.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
Configuration config = resources.getConfiguration();
resources.updateConfiguration(config, dm);
下面是我写的代码,可以参考,也是抄的各家博文
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public static void setLanguage(Context context) {
//读取SharedPreferences数据,默认选中第一项
SharedPreferences preferences = context.getSharedPreferences("language", Context.MODE_PRIVATE);
int language = preferences.getInt("language", 0);
//根据读取到的数据,进行设置
Resources resources = context.getResources();
//注意application的context也更新,不然getString的国际化不生效
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
Configuration configuration = resources.getConfiguration();
switch (language){
case 0:
Locale locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList localeList = LocaleList.getDefault();
locale = localeList.get(localeList.size() - 1);
} else {
locale = Locale.getDefault();
}
configuration.setLocale(locale);
break;
case 1:
configuration.setLocale( Locale.CHINESE);
break;
case 2:
configuration.setLocale(new Locale( "bo", "rCN" , ""));
break;
default:
break;
}
resources.updateConfiguration(configuration,displayMetrics);
}
这里还是有东西需要注意的,使用 context 对语言进行设置是不完全的,比如你使用的是 activity 的 context 进行设置的话,在 java 代码总使用 getString 获取字符串是不生效的,需要将 application 的 context 也设置一遍:
//写在第一个界面(LoginActivity)中,在第一个界面设置了就可以
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
//设置多语言
LanguageUtil.setLanguage(getContext());
//注意application的context也更新,不然getString的国际化不生效
LanguageUtil.setLanguage(getApplicationContext());
}
//注意需要写在 setContentView 前面
setContentView(R.layout.com_aty_login);
这里注意两个都需要设置,不然多语言设置会不完全。并且 application 的 context 不能使用 application 代替,不然不会生效。
Locale的设置
注意 Locale 默认提供的区域并不多,至少从里面找不到藏语之类的,还好我们可以自己创建
Locale locale;
//默认提供
locale = Locale.CHINESE;
//自行创建
locale = new Locale( "bo", "rCN" , "");
使用 ctrl + p 很容易知道里面的参数,这里其实和我们在 Android Studio 中创建的情况差不多,前一个是语言简称,后面是国家区域,第三个我也不清楚,可以不填。
兼容设置
根据网上博客提示,好像系统版本高于 7.0 会出现问题,大概就是高于 7.0 获取的默认 Locale 是一个列表,我直接用下面代码在安卓10是没问题的,默认语言也是对的:
Locale locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList localeList = LocaleList.getDefault();
locale = localeList.get(localeList.size() - 1);
} else {
locale = Locale.getDefault();
}
多语言的持久化
我们设置的多语言不能因为应用被杀进程就消失了,所以应该使用 SharedPreferences 储存起来,这里简单写一下储存的吧,获取的在前面有:
private void changeLanguage() {
//创建单选框
final AlertDialog.Builder builder = new AlertDialog.Builder(UserMoreAty.this);
builder.setSingleChoiceItems(new String[]{getString(R.string.user_language_auto), getString(R.string.user_language_chianese), getString(R.string.user_language_tibetan)},
getSharedPreferences("language", Context.MODE_PRIVATE).getInt("language",0),
new DialogInterface.OnClickListener() {
//点击单选框某一项以后
public void onClick(DialogInterface dialogInterface, int i) {
//将选中项存入SharedPreferences,以便重启应用后读取设置
SharedPreferences preferences = getSharedPreferences("language", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("language",i);
editor.apply();
dialog.dismiss();
//退出登录生效
Intent intent = new Intent(activity, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | iIntent.FLAG_ACTIVITY_CLEAR_TASK);
iactivity.startActivity(intent);
}
});
dialog = builder.create();
dialog.show();
}
多语言生效问题
如上面代码设置所写,需要将 activity 栈中的页面清除,并重新开启 activity,一般来说直接让重新登陆就可以(我这设置写在登陆界面里)。
对于无感觉切换语言,我是觉得不太可能,毕竟界面已经刷新出来了,重新启动 activity 肯定会闪一下的,网上有人说下面办法可以解决闪屏问题,我没试过,可以参考:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--禁用窗口的预览动画-->
<item name="android:windowDisablePreview">true</item>
</style>
结语
东西不是很难,写下来发现写的有点乱,但是尽量把重要的点都写出来了,稍微总结一下:
- 创建不同语言的资源文件
- 使用资源文件中的字符串编写代码和布局文件
- 提供设置多语言的功能,储存到 SharedPreferences 中
- 设置选定语言后清空 activity 栈,根据需要重新开启一个页面
- 每次登录,在第一个界面读取 SharedPreferences 数据,设置选中语言
end
更多推荐
所有评论(0)