Android 8.0中多语言适配解决方法

起因

做的一个项目里需要用到用户手动进行多语言切换,当我把之前项目的语言切换代码复制过来时却发现无法生效,但该代码可以在一些旧设备上使用,本文会讲解此故障出现的原因以及如何进行正确的多语言切换。

问题

之前一直使用updateConfiguration()的方式进行多语言切换,但是在API24之后,这个方法废弃了,在API24和25上都可以正常使用,没有任何问题,查了一遍都没有发现问题,旧设备上也可以正常使用,故将问题的原因定位在使用废弃API上,通过查询资料得知由于在Android 7.0后Android更改了多语言机制,导致旧API被废弃。

Samsung在Android 8.0中的语言设置截图

在Android 7.0之前,语言只可以设置一个,而在Android 7.0或更高版本的Android中,用户可以指定多个语言,设置语言顺序,许多人对于这种方式并不理解,实际上这是Android更加完善的一种表现。

世界上有许多国家或地区使用多种语言作为其官方语言,如香港特别行政区,官方和法定语言为中文和英文。旧版本的Android仅支持一种语言设置,当应用程序不包含目标设备语言时就会使用默认values/strings.xml里的语言,在许多非英语国家特别是中国,程序员非常喜欢将中文写入默认strings.xml里,这就导致即使程序适配了其他语言,当遇到一些没有在对应语言的strings.xml里进行适配的字符串时,会使用默认strings.xml里的字符串,从而导致语言混乱。Android 8.0后的多语言适配为用户提供了第二语言的选项,当软件没有进行第一语言的适配时,会默认使用第二语言,以此类推到第三语言、第四语言,避免出现语言混乱的问题。

解决方法

自定义一个继承于ContextWrapper的NsContextWrapper类,在这个类里对语言进行切换,通过判断系统版本是否为8.0或更高版本来进行不同的切换操作。

代码(Kotlin):

class NsContextWrapper(base: Context) : ContextWrapper(base) {

   companion object {
       fun wrap(context: Context?, newLocale: Locale): ContextWrapper {
           var context = context
           val res = context!!.resources
           val configuration = res.configuration
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
               configuration.setLocale(newLocale)
               val localeList = LocaleList(newLocale)
               LocaleList.setDefault(localeList)
               configuration.locales = localeList
               context = context.createConfigurationContext(configuration)
           } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
               configuration.setLocale(newLocale)
               context = context.createConfigurationContext(configuration)
           }
           return ContextWrapper(context)
       }
   }
}

自定义ContextWrapper后,如果要对所有Activity生效,则需要再自定义个继承于Activity的BaseActivity类,其他Activity通过继承这个自定义的Activity从而达到生效的目的,在BaseActivity类的attachBaseContext方法中,覆盖如下代码:

代码(Kotlin):

override fun attachBaseContext(newBase: Context?) {
   //这里可自己进行语言判断操作
   var context = NsContextWrapper.wrap(newBase, Locale.TAIWAN)
   super.attachBaseContext(context)
}

这样就可以进行不同版本Android的多语言切换了,BaseActivity里的代码并没有做逻辑判断,开发者可以通过数据库或SharedPreference来达到获取设置语言的目的。


UP能力有限,如果错误请指出,谢谢!

本文禁止转载或摘编

-- --
  • 投诉或建议
评论