以前老是有開發者反饋我應用切換了語言,但是工具類獲取的 string
卻沒有發生改變。其實這個問題很簡單,你切換語言的 Context
只做用在了你的 Activity
上,並無對你的 Application
作一樣的操做,知道了這點,那麼解決問題就很簡單了,爲了省事,我給你們封裝了 LanguageUtils
,直接一行代碼即可完成多語言的切換,相似微信的語言切換分分鐘即可完成。java
Gradle:android
implementation 'com.blankj:utilcode:latest_version'
複製代碼
applySystemLanguage: 應用系統語言
applyLanguage : 應用語言
複製代碼
若是咱們的應用不設置 android:configChanges="locale|layoutDirection"
,那麼應用是跟隨系統語言設置的變化而變化的,好比你應用適配了英語(values-en-rUS
)和簡體中文(values-zh-rCN
),那麼你去設置裏切換成英語的話,返回到你應用中,你的 Activity
會從新建立一遍,把 Activity#Resource#Configuration#Locale
設置爲當前系統語言,這樣就達到了跟隨系統語言設置的變化而變化,但 Application
並無重啓,因此這就致使了一開說到的問題。git
要解決跟隨系統變化這一點的話,只須要在 Activity#onCreate
的生命週期中把 Application#Resource#Configuration#Locale
設置爲系統的 Locale
便可,那麼系統的 Locale
怎麼讀取呢,知道以前屏幕適配方案的人應該也能想到這一方式:Resources.getSystem().getConfiguration().locale
,這樣,咱們的 Application
便也切換成了系統語言,注意更新 Locale
須要兼容下高版本,調用具體代碼能夠參照以下:github
private static void updateLanguage(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();
Locale contextLocale = config.locale;
if (equals(contextLocale.getLanguage(), locale.getLanguage())
&& equals(contextLocale.getCountry(), locale.getCountry())) {
return;
}
DisplayMetrics dm = resources.getDisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale);
context.createConfigurationContext(config);
} else {
config.locale = locale;
}
resources.updateConfiguration(config, dm);
}
複製代碼
那麼若是是應用內切換語言呢?咱們能夠仿照系統切換語言的方式,把咱們本身全部的 Activity
全關掉,而後啓動首頁的 Activity
便可,在打開的 Activity#onCreate
中把 Activity
和 Application
的 Locale
都設置爲咱們設置的語言便可,固然,這份設置是須要保存下來的,根據你的需求來肯定是要保存在服務端仍是本地。那麼怎麼關閉全部的 Activity
呢?咱們能夠經過增長 Intent
的 flag 爲 Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
便可,相關代碼以下所示:bash
private static void applyLanguage(@NonNull final Locale locale, final String activityClassName, final boolean isFollowSystem) {
if (isFollowSystem) {// 若是是跟隨系統,那麼 sp 就什麼都不存
SPUtils.getInstance().put(KEY_LOCALE, "");
} else {// 不然把設置的語言保存下來,在 onCreate 中應用該語言
String localLanguage = locale.getLanguage();
String localCountry = locale.getCountry();
SPUtils.getInstance().put(KEY_LOCALE, localLanguage + "$" + localCountry);
}
updateLanguage(Utils.getApp(), locale);// 更新 Application 的語言
Intent intent = new Intent();
String realActivityClassName// 若是傳入的 activityClassName 爲空,那麼啓動 launcher Activity。
= TextUtils.isEmpty(activityClassName) ? getLauncherActivity() : activityClassName;
intent.setComponent(new ComponentName(Utils.getApp(), realActivityClassName));
intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
);
Utils.getApp().startActivity(intent);// 關閉其餘 Activity 並啓動 realActivityClassName 的 Activity
}
// 工具類調用此函數是在 ActivityLifecycleCallbacks#onActivityCreated 中
static void applyLanguage(@NonNull final Activity activity) {
final String spLocale = SPUtils.getInstance().getString(KEY_LOCALE);// 獲取保存的語言
if (TextUtils.isEmpty(spLocale)) {// 爲空說明是跟隨系統走,那麼更新系統語言便可
Locale sysLocale = Resources.getSystem().getConfiguration().locale;
updateLanguage(Utils.getApp(), sysLocale);
updateLanguage(activity, sysLocale);
return;
}
// 讀取 sp 保存下來的語言並應用該語言
String[] language_country = spLocale.split("\\$");
if (language_country.length != 2) {
Log.e("LanguageUtils", "The string of " + spLocale + " is not in the correct format.");
return;
}
Locale settingLocale = new Locale(language_country[0], language_country[1]);
updateLanguage(Utils.getApp(), settingLocale);
updateLanguage(activity, settingLocale);
}
複製代碼
基於以上分析:微信
Application
的語言。LanguageUtils.applyLanguage(Locale.你要設置的語言, "com.blankj.launcher.pkg.MainActivity/* 切換語言後你要跳轉到的頁面,若是爲空,則啓動應用的 launcher Activity */")
便可;LanguageUtils.applySystemLanguage(""/* 切換語言後你要跳轉到的頁面,若是爲空,則啓動應用的 launcher Activity */);
便可。功能其實很簡單,但老是缺乏人能把它分析得透徹,從而作得很完美分享出來,但願我此次的分享能讓你看到這一點,從而提高你以後的技能。app
字節跳動大量招人中,歡迎向 blankj@qq.com 投遞您的簡歷。函數