修改應用級 Configuration.locale,並重建 Activity 使新語言生效。不影響系統語言。
public void setAppLanguage(Context context, String languageCode) {
// 1. 設置 Locale
Locale locale = new Locale(languageCode); // 如 "zh", "en", "zh_CN"
Locale.setDefault(locale); // JVM 級默認
// 2. 更新 Resources Configuration
Resources res = context.getResources();
Configuration config = res.getConfiguration();
config.locale = locale;
// API 17+ 支持多語言
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLayoutDirection(locale);
}
res.updateConfiguration(config, res.getDisplayMetrics());
// 3. 保存選擇 (SharedPreferences)
PreferenceManager.getDefaultSharedPreferences(context)
.edit().putString("app_language", languageCode).apply();
}
// 1. 工具類
public class LocaleHelper {
public static Context setLocale(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration config = context.getResources().getConfiguration();
config.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLayoutDirection(locale);
}
return context.createConfigurationContext(config);
}
public static Context onAttach(Context context) {
String lang = PreferenceManager.getDefaultSharedPreferences(context)
.getString("app_language", "en");
return setLocale(context, lang);
}
}
// 2. BaseActivity 攔截 attachBaseContext
public class BaseActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleHelper.onAttach(newBase));
}
}
// 3. 語言切換觸發重建
public void changeLanguage(String lang) {
LocaleHelper.setLocale(this, lang);
recreate(); // 關鍵:重建 Activity 使佈局/字符串重新加載
}
@RequiresApi(api = Build.VERSION_CODES.N)
public static Context updateLocale(Context context, Locale locale) {
Configuration config = context.getResources().getConfiguration();
LocaleList localeList = new LocaleList(locale);
config.setLocales(localeList);
config.locale = locale; // 兼容舊 API
return context.createConfigurationContext(config);
}
String[] languages = {"English", "中文", "日本語"};
String[] codes = {"en", "zh", "ja"};
ArrayAdapter adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, languages);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override public void onItemSelected(AdapterView> parent, View view, int pos, long id) {
changeLanguage(codes[pos]);
}
@Override public void onNothingSelected(AdapterView> parent) {}
});
// 初始化選中項
String saved = prefs.getString("app_language", "en");
for (int i = 0; i < codes.length; i++) {
if (codes[i].equals(saved)) { spinner.setSelection(i); break; }
}
| 項目 | 建議 |
|---|---|
| 重建 Activity | recreate() 會銷毀重建,確保 ViewModel/onSaveInstanceState 處理狀態保存 |
| 系統語言跟隨 | 提供「跟隨系統」選項,清除 SP 中語言設置,attachBaseContext 讀取不到時用系統默認 |
| 右到左語言 (RTL) | config.setLayoutDirection(locale) + 佈局使用 start/end 而非 left/right |
| 第三方庫 | 部分庫 (如圖片加載) 可能緩存舊語言資源,需配合清理 |
| 測試 | 覆蓋 LTR/RTL、多語言字符集、字體縮放、佈局溢出 |
```
系統設置中自動顯示應用支持的語言選項,用戶可直接在系統級切換。