Android多语言切换实现--Java实现
前言
最近在想宝可梦的那样记账要加什么功能好呢?突然想到,不如实现多语言手动切换(国际化),方便那些为了开Google Assistant而把语言设置成英文的朋友可以在该App使用中文界面。
需求
- 可以随着系统切换语言而切换语言(即跟随系统),不支持的语言显示默认(默认为英文)
- 用户可以自由选择自己想用的语言,且不会随着系统切换语言或者应用重启而还原
虽然看着简单,但是实现起来还是遇到了点问题
原理
参照 Android Developer官网 上的描述,Configuration 包含了设备的所有的配置信息,这些配置信息会影响应用获取的资源。例如string资源,就是在不同的res/value-xx下放置不同语言的strings.xml实现字符的本地化,然后根据Configuration的locale属性来判断该取哪种语言的string资源,而这个value-xx目录的选择是根据locale这项的值来决定的。
如zh中文,就会选择value-zh目录,如果没有匹配到(即res中没有value-zh目录)就使用默认的value目录中的字符资源。
那么我们只需要想办法改变并重新加载Configuration即可!!!
注:
value-en、value-zh-rCN、values-zh-rTW分别表示英文、简体中文、繁体中文三种语言
初次尝试
1. 添加多语言文件
在不同的value文件夹下(例如value、value-en、value-zh-rCN、values-zh-rTW文件夹)添加不同语言的string.xml文件,我们的项目添加了英文、简体中文、繁体中文三种语言。
翻译之类的就自行翻译啦~繁体可以找个简繁转换网站。
2. 更新 Configuration 中的 locale 属性来实现app语言的切换
主要代码如下:
|
|
我们用了Locale中的预设值Locale.ENGLISH、Locale.TRADITIONAL_CHINESE和Locale.SIMPLIFIED_CHINESE,如果你需要设置的语言没有预设值,你可以自己新建一个Locale对象,具体自行 Google 吧。
注:跟随系统设置是Locale.getDefault()
3. 重启 HomeActivity
我们的 App 有个启动页WelcomeActivity,类似微信那个小人启动页,如果从欢迎页重启,并不是一个好的体验,应该和微信的语言设置一样,直接回到HomeActivity,而不是从 WelcomeActivity重新打开。实现其实也很简单,代码如下:
|
|
4. 持久化存储语言设置
按照上述三个步骤,你应该已经可以看到了改变语言的效果了,但是当你杀掉应用,重新打开,发现设置又失效了。这是因为应用重启后会读取设备默认的Configuration信息,其中和语言相关的locale属性也会变成默认值,也就是你在系统设置中选择的语言。
当你的应用需要由用户单独设置语言,而不是仅仅跟随系统语言,你就需要持久化存储用户的设置信息了。你可以选择数据库、或SharedPreferences来存储设置信息,存一个Type的int值即可。
5. 根据本地缓存的type获取对应的locale
其中7.0以上的系统需要另做处理(在后面会讲处理兼容性问题),具体代码如下:
|
|
6. 在AppApplication中初始化时设置本地语言
用于每次启动APP后切换到本地缓存的语言
|
|
7. 在BaseActivity的OnCreate()方法中设置语言
用于处理每次切换系统语言后app语言会跟随系统变化的问题。
在这一步之前会遇到一个问题:当从应用中切出去,改变了系统语言的设置,当再切应用的时候,我发现语言也会变成系统语言(而我并没在应用内设置跟随系统)。
引用自@写代码的猴子的文章: 简单来说,上一步中,我们在 App 启动时,读取了用户的设置信息,并应用到
Configuration的locale属性上,然后通过resources.updateConfiguration(config, dm)改变了应用的配置信息(Configuration)并生效,保证我们的应用读取的string资源都是用户设置语言对应的资源。在我们改变系统的语言之后,再回到我们的应用中,此时的Configuration的locale属性就会发生变化了,不再是我们刚才自己的在应用启动时设置的了,而是变成了系统的设置了。
那么解决办法也很简单,我们都知道 activity 有生命周期,在切回我们的应用时,在显示的 activity 的生命周期中做一些处理就好了(有点粗暴~)
在实际开发中,我们会建立很多个 activity,而每一个 activity 都要更改语言的。这个时候我们如果一个个做处理是不是很麻烦?这个时候我们利用面向对象语言的继承特性即可,创建一个BaseActivity,在BaseActivity 中处理后其他 Activity 都去继承BaseActivity就好了。@写代码的猴子的文章中说评论中提到,在改变了系统设置之后,回到应用会重走activity的onCreate(如果按照Activity的生命周期看其实应该是onResume才对),那就在OnCreate中处理一下:
|
|
|
|
解决7.0以上系统存在的兼容问题——跟随系统语言失效
Android 7.0 语言设置爬坑这篇文章讲的很详细,具体还可以参考官方文档和官方API
如果不做兼容,可能会出现以下情况:在 App 中,语言默认选择的是「跟随系统」(系统语言列表中「简体中文」是第一个),然后选择「英语」,之后再切换回「跟随系统」,发现语言并没切回「简体中文」,而还是「英语」。
由于 Android7.0 以上Configuration将通过LocaleList来管理语言,并且系统切换语言后,系统默认语言可能并不在LocaleList顶部。
经过调试发现:如果在 App 中手动选择(切换)过语言则在LocaleList中系统语言是第二个,否则是第一个。
所以,获取当前系统locale,代码如下:
|
|
缺点
但是这个做出来的效果是每次启动都会重启一次Activity,强迫症的我表示根本受不了😂,而且横竖屏切换后会有语言变成系统语言的问题