Android实现app内的语言切换功能
我在目前所在的公司負責一個app項目的維護,最近需要對這個項目進行國際化,適配10多個國家的語言,在實現國際化過程中,遇到了很多問題,最麻煩的就是翻譯了,得一個個將翻譯從excel復制到資源文件中,還得保證key和value一一對應,稍不注意就容易出錯,當然也有一些自動化的工具可以替代手工復制,但需要excel滿足一定的規范,不然會出現一些差錯。還有就是其他語言下的ui適配,有些文字翻譯成其他語言,就會變得很長,設計的時候也沒考慮這些,所有語言都使用同一套設計,導致很多文字顯示不全,或者出現重疊的問題。另外一個就是app內的語言切換功能,其實這個功能實現很簡單,系統有相應的api,但是需要注意這里面有幾個坑,不要向我一樣踩到了。
切換語言有兩個方法可以實現,分別是
1、Resources public void updateConfiguration(Configuration config, DisplayMetrics metrics) 2、Context Context createConfigurationContext(Configuration overrideConfiguration)方法1屬于Resources的,已經被棄用了。代碼:
Resources resources = context.getResources(); Configuration config = resources.getConfiguration(); DisplayMetrics dm = resources.getDisplayMetrics(); Locale locale = new Locale("vi", "vn"); config.setLocale(locale); resources.updateConfiguration(config, dm);使用該方法,在不同手機上有不同的表現,
魅族手機在 application 的 onCreate 方法中設置即可生效,
但華為手機需要在 activity 的 onCreate 方法中設置才生效。
所以穩妥的方法是,
在Launcher activity 中判斷如果有設置語言,使用該方法設置語言。
如果用戶在設置中更改了語言,調用主 Activity 的 recreate 方法重建,不重建不會生效,因此還要在主 Activity 的 onCreate 判斷 savedInstanceState 不為空時使用該方法切換語言。
若設置了語言,同時也要監聽系統語言發生改變的廣播,收到這個廣播后,使用該方法切換語言。
既然這個被棄用了,那可能是有問題的。在測試過程中確實發現了不少問題:
問題1、Android 9 上失效:
在設置中更改語言后,回到主 Activity ,語言確實更改成功了,但是打開其他頁面,語言還是上次設置的語言。關閉app重新打開,每個頁面的語言又都是對的。解決方法是必須在每個頁面都設置。
問題2、華為手機中失效:
在app某一頁面切換了導航欄顯示狀態后,進入其他頁面或返回頁面時,因為配置(屏幕高度)改變了,會導致語言變成系統默認的語言。此時注冊的配置改變的廣播并不會收到廣播,但會調用 MyApplication 中的onConfigurationCahnged 方法(會在Activity onCreate方法之前調用)。所以需要在導航欄顯示狀態發生改變后切換語言,但是不能直接在 Application 中來切換,這樣切換對于 Activity 沒有作用(Application 和Activity 的 Context 不一樣)。也不能在 Application 中發送一個自定義的 Action 的廣播來通知廣播接收器修改,這樣的修改對于 Activity 也是沒有作用的(必須是自定義的 Action,如果使用系統的配置改變的 Action 會報錯,只有系統權限才能發送該廣播)。解決方法是在 Application 中注冊 registerActivityLifecycleCallbacks,監聽 Activity 的生命周期,當導航欄顯示狀態發生變化時,如果是進入新頁面就在 onActivityCreated 里面使用該方法設置語言,如果是返回上一級頁面,在 onActivityResumed 里面使用該方法設置語言。
基于上面的問題,我們應該使用方法二,代碼:
override fun attachBaseContext(newBase: Context) {val configuration = newBase.resources.configurationconfiguration.setLocale(Locale.ENGLISH)val createContext = newBase.createConfigurationContext(configuration)super.attachBaseContext(createContext) }沒錯需要在 attachBaseContext 方法中修改,把修改后的Context 設置給 Activity 或 Appcalition 。
該方法需要在每個頁面中都設置,所以可以寫一個 BaseActivity ,在里面統一設置。
這樣就完了嗎?不可能的! 這兩種方法都會遇到一個問題,若你的 app 加載了 WebView 你會發現語言又變回了系統默認的默認語言!!!
在 Android 7 之前WebView的渲染是通過Android System webView來實現的。但是在Android7之后WebView會被作為一個應用程序的方式服務于各個三方APP。由于WebView這里是作為一個單獨的應用程序,所以他不會被綁定到你自己APP設置的Local上。不僅如此,WebView還會把語言變成設備的Local設置。然后相應的資源文件也會被變成設備語言下的資源文件這樣就導致了只要打開了含有WebView的頁面,應用內語言設置就失效的問題。
上面是網上搜到的解釋。
所以在 WebView 加載后還需要設置一遍語言。
或者在 app 啟動時就加載一次 WebView ,然后在設置語言,只要 WebView 第一次加載后修改了語言,后面再加載便不會重置為系統語言。
需要注意的地方:
1、部分手機需要給Local設置語言還有國家才成效,所以最好都設置國家或地區。
2、只在 Application 和 Activity 中的某一個修改了語言,它們的 Local 中的語言是不同的。
3、某些手機中,彈出Toast時如果使用的是getApplicationContext(),彈出的語言是系統默認的語言,所以最好都傳 Activity 的 Context .
~~這下子就完美了。
總結
以上是生活随笔為你收集整理的Android实现app内的语言切换功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 乔布斯的魔力演讲
- 下一篇: Android-电池优化Doze和Sta