Android使用AndroidUtilCode實(shí)現(xiàn)多語(yǔ)言
一、項(xiàng)目中配置多語(yǔ)言
多語(yǔ)言的實(shí)現(xiàn)是通過AndroidUtilCode實(shí)現(xiàn)的,表示感謝!
項(xiàng)目里面有4種語(yǔ)言:中文,英文,德文,俄文。文件夾如下:
配置多語(yǔ)言的思路是:
1、判斷是否為國(guó)內(nèi)版本,如果為國(guó)內(nèi)版本則設(shè)置為簡(jiǎn)體中文
2、 如果為國(guó)外版本,獲取用戶之前設(shè)置的App語(yǔ)言,如果用戶之前有設(shè)置App語(yǔ)言,則設(shè)置為之前用戶設(shè)置的語(yǔ)言;如果用戶之前沒有設(shè)置App語(yǔ)言則獲取手機(jī)系統(tǒng)的語(yǔ)言。
3、判斷當(dāng)前手機(jī)系統(tǒng)的語(yǔ)言是否App有做語(yǔ)言適配,如果有適配則設(shè)置成跟手機(jī)系統(tǒng)一樣的語(yǔ)言,如果沒有適配則設(shè)置為英文。
二、具體實(shí)現(xiàn)
1、初始化PropertiesUtil和MMKV,具體代碼請(qǐng)參考上篇博客
2、在BaseApplication中設(shè)置語(yǔ)言
abstract class BaseApplication : Application() { abstract fun init() override fun onCreate() { super.onCreate() init() PropertiesUtil.init(this) MMKV.initialize(this) MMKVUtil.setUserId(1000L) //設(shè)置App語(yǔ)言 setAppLanguage() } /** * 判斷是否為國(guó)內(nèi)版本,如果為國(guó)內(nèi)版本則設(shè)置為簡(jiǎn)體中文 * 如果為國(guó)外版本,獲取用戶之前設(shè)置的App語(yǔ)言, * 如果用戶之前有設(shè)置App語(yǔ)言,則設(shè)置為之前用戶設(shè)置的語(yǔ)言 * 如果用戶之前沒有設(shè)置App語(yǔ)言則獲取手機(jī)系統(tǒng)的語(yǔ)言 * 判斷手機(jī)系統(tǒng)的語(yǔ)言是否App有做語(yǔ)言適配,如果有適配則設(shè)置成跟手機(jī)系統(tǒng)一樣的語(yǔ)言 * 如果App沒有對(duì)當(dāng)前系統(tǒng)語(yǔ)言做適配則設(shè)置為英文 */ private fun setAppLanguage() { if (PropertiesUtil.isCN()) { //國(guó)內(nèi)版本 LanguageUtils.applyLanguage(Locale.SIMPLIFIED_CHINESE, false) } else { MMKVUtil.getLanguage().also { if (it.isNotEmpty()) { setLanguageAndBackCountry(it) } else { //獲取系統(tǒng)語(yǔ)言 LanguageUtils.getSystemLanguage().country.also { country -> setLanguageAndBackCountry(country).also { value -> //保存設(shè)置的語(yǔ)言 MMKVUtil.setLanguage(value) } } } } } } private fun setLanguageAndBackCountry(it: String): String { return when (it) { LanguageType.CN.name -> { LanguageUtils.applyLanguage(Locale.SIMPLIFIED_CHINESE, false) it } LanguageType.US.name -> { LanguageUtils.applyLanguage(Locale.ENGLISH, false) it } LanguageType.DE.name -> { LanguageUtils.applyLanguage(Locale.GERMANY, false) it } LanguageType.RU.name -> { LanguageUtils.applyLanguage(Locale("ru"), false) it } else -> { LanguageUtils.applyLanguage(Locale.ENGLISH, false) LanguageType.US.name } } } }
3、切換語(yǔ)言
比如設(shè)置為德文,按鈕觸發(fā):
MMKVUtil.setLanguage(LanguageType.DE.name) LanguageUtils.applyLanguage(Locale.GERMANY, false) //true:重啟App false:不重啟App
4、注意gradle配置resConfigs
不要限制為只有中文,比如:resConfigs "zh-rCN", "en"
三、AndroidX和多進(jìn)程存在的問題
1、多進(jìn)程讀取Configuration
時(shí)發(fā)現(xiàn)其他進(jìn)程與主進(jìn)程獲取的Configuration
值不一致,導(dǎo)致主進(jìn)程切換語(yǔ)言后其他語(yǔ)言并沒有切換成功。
2、AndroidX切換失敗的問題,具體可以看下這篇博客【踩坑記錄】多語(yǔ)言切換在Androidx失效
解決辦法:重寫Activity的attachBaseContext
方法,修改Context
/** * 多語(yǔ)言的切換類, 解決多進(jìn)程切換語(yǔ)言失敗的問題以及AndroidX多語(yǔ)言切換失效的問題 * 解決由于 WebView 初始化會(huì)修改 Activity 語(yǔ)種配置,間接導(dǎo)致 Activity 語(yǔ)種會(huì)被還原,所以需要你手動(dòng)重寫 WebView 對(duì)這個(gè)問題進(jìn)行修復(fù) */ object MultiLanguageUtil { fun getAttachBaseContext(context: Context): Context { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { configAppcompatLanguage(setAppLanguageApi24(context)) } else { setAppLanguage(context) configAppcompatLanguage(context) } } /** * 設(shè)置應(yīng)用語(yǔ)言 */ @Suppress("DEPRECATION") private fun setAppLanguage(context: Context) { val resources = context.resources val displayMetrics = resources.displayMetrics val configuration = resources.configuration // 獲取當(dāng)前系統(tǒng)語(yǔ)言,默認(rèn)設(shè)置跟隨系統(tǒng) val locale = getLocale() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { configuration.setLocale(locale) } else { configuration.locale = locale } resources.updateConfiguration(configuration, displayMetrics) } /** * 兼容 7.0 及以上 */ @TargetApi(Build.VERSION_CODES.N) fun setAppLanguageApi24(context: Context): Context { val locale = getLocale() val resource = context.resources val configuration = resource.configuration configuration.setLocale(locale) configuration.setLocales(LocaleList(locale)) return context.createConfigurationContext(configuration) } private fun configAppcompatLanguage(context: Context): Context { val configuration = context.resources.configuration //兼容appcompat 1.2.0后切換語(yǔ)言失效問題 return object : ContextThemeWrapper(context, R.style.Base_Theme_AppCompat_Empty) { override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) { overrideConfiguration?.setTo(configuration) super.applyOverrideConfiguration(overrideConfiguration) } } } private fun getLocale(): Locale { return when (CacheUtil.getInt(GlobalConstants.LANGUAGE_KEY, true)) { 0 -> { Locale.SIMPLIFIED_CHINESE } 1 -> { Locale.ENGLISH } 2 -> { Locale.GERMANY } 3 -> { Locale("ru") } else -> Locale.ENGLISH } } /** * 解決WebView多語(yǔ)言失效的問題 */ fun updateLanguage(context: Context) { val resources = context.resources val config = resources.configuration val settingLanguage = getLocale().language val systemLanguage = config.locales[0].language if (settingLanguage != systemLanguage) { setLocale(config, Locale(settingLanguage)) resources.updateConfiguration(config, resources.displayMetrics) } } private fun setLocale(config: Configuration, locale: Locale?) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val localeList = LocaleList(locale) config.setLocales(localeList) } else { config.setLocale(locale) } } else { config.locale = locale } } }
獲取appContext
lateinit var appContext: Application //BaseApplication中調(diào)用方法獲取Application的上下文 fun BaseApplication.getContext(application: BaseApplication) { appContext = application }
四、WebView導(dǎo)致的語(yǔ)言重置的問題
由于 WebView 初始化會(huì)修改 Activity 語(yǔ)種配置,間接導(dǎo)致 Activity 語(yǔ)種會(huì)被還原,所以需要你手動(dòng)重寫 WebView 對(duì)這個(gè)問題進(jìn)行修復(fù),如下:
/** * 由于 WebView 初始化會(huì)修改 Activity 語(yǔ)種配置,間接導(dǎo)致 Activity 語(yǔ)種會(huì)被還原回去,所以需要你手動(dòng)重寫 WebView 對(duì)這個(gè)問題進(jìn)行修復(fù) */ class LanguagesWebView( context: Context, @Nullable attrs: AttributeSet?, defStyleAttr: Int ) : WebView(context, attrs, defStyleAttr) { constructor(context: Context) : this(context, null) {} constructor(context: Context, @Nullable attrs: AttributeSet?) : this( context, attrs, 0 ) init { //修復(fù) WebView 初始化時(shí)會(huì)修改Activity 語(yǔ)種配置的問題 MultiLanguageUtil.updateLanguage(context) } }
項(xiàng)目中用這個(gè)WebView即可。這個(gè)問題在華為手機(jī)鴻蒙系統(tǒng)上會(huì)出現(xiàn)。
五、枚舉類的多語(yǔ)言實(shí)現(xiàn)
枚舉類型是線程安全的,并且只會(huì)裝載一次,這就導(dǎo)致下面的寫法導(dǎo)致枚舉的err
值在切換語(yǔ)言后不會(huì)發(fā)生變化。
enum class Error( var code: Int, var err: String) { /** * 未知錯(cuò)誤 */ UNKNOWN(1000,appContext.getString(R.string.error_1000)), /** * 解析錯(cuò)誤 */ PARSE_ERROR(1001, appContext.getString(R.string.error_1001)), /** * 網(wǎng)絡(luò)錯(cuò)誤 */ NETWORK_ERROR(1002, appContext.getString(R.string.error_1002)), /** * 證書出錯(cuò) */ SSL_ERROR(1004, appContext.getString(R.string.error_1004)), /** * 連接超時(shí) */ TIMEOUT_ERROR(1006, appContext.getString(R.string.error_1002)); fun getValue(): String { return err } fun getKey(): Int { return code } }
那么如果做枚舉類的多語(yǔ)言適配呢? 代碼如下:
enum class Error(private val code: Int, private val err: Int) { /** * 未知錯(cuò)誤 */ UNKNOWN(1000, R.string.error_1000), /** * 解析錯(cuò)誤 */ PARSE_ERROR(1001, R.string.error_1001), /** * 網(wǎng)絡(luò)錯(cuò)誤 */ NETWORK_ERROR(1002, R.string.error_1002), /** * 證書出錯(cuò) */ SSL_ERROR(1004, R.string.error_1004), /** * 連接超時(shí) */ TIMEOUT_ERROR(1006, R.string.error_1002); fun getValue(): String { return appContext.getString(err) } fun getKey(): Int { return code } }
因?yàn)樽址膇d是固定的不會(huì)發(fā)生變化,所以即使枚舉類只會(huì)裝載一次也不會(huì)有影響,通過getValue
就能取到正確語(yǔ)言的字符串。
參考
以上就是Android使用AndroidUtilCode實(shí)現(xiàn)多語(yǔ)言的詳細(xì)內(nèi)容,更多關(guān)于Android AndroidUtilCode多語(yǔ)言的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android:Field can be converted to a local varible.的解決辦法
這篇文章主要介紹了Android:Field can be converted to a local varible.的解決辦法的相關(guān)資料,希望通過本文能幫助到大家,讓大家遇到這樣的問題輕松解決,需要的朋友可以參考下2017-10-10Android仿微信聯(lián)系人列表字母?jìng)?cè)滑控件
這篇文章主要為大家詳細(xì)介紹了Android仿微信聯(lián)系人列表字母?jìng)?cè)滑控件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Android實(shí)現(xiàn)Bitmap位圖旋轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)Bitmap位圖旋轉(zhuǎn)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04Android實(shí)現(xiàn)下拉刷新的視圖和圖標(biāo)的旋轉(zhuǎn)
本篇文章主要介紹了Android實(shí)現(xiàn)下拉刷新的視圖和圖標(biāo)的旋轉(zhuǎn)的實(shí)例,具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-03-03Android build.gradle版本名打包配置的方法
這篇文章主要介紹了Android build.gradle版本名打包配置的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02Android最新版本開發(fā)環(huán)境搭建圖文教程
這篇文章主要為大家詳細(xì)介紹了Android最新版本開發(fā)環(huán)境搭建圖文教程,重點(diǎn)在于配置JDK,以及adt-bundle,感興趣的小伙伴們可以參考一下2016-07-07Android編程之界面實(shí)現(xiàn)全屏顯示的方法(2種方法)
這篇文章主要介紹了Android編程之界面實(shí)現(xiàn)全屏顯示的方法,結(jié)合實(shí)例分析了Java代碼中設(shè)置與Manifest文件設(shè)置2種實(shí)現(xiàn)方法,需要的朋友可以參考下2016-01-01android實(shí)現(xiàn)將位置信息寫入JPEG圖片文件
下面小編就為大家?guī)硪黄猘ndroid實(shí)現(xiàn)將位置信息寫入JPEG圖片文件。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03