区域设置总是在 onCreate 之后重置

Locale always get reset after onCreate

我尝试在应用程序中设置语言环境,首先 运行 它起作用了。但是,在 onCreate() 之后(旋转)将重置为默认语言,重置后我无法在应用程序中更改语言。

我使用 SharePreference 来保存语言环境值

PrefUtils.java 从 SharePreference

获取价值
public class PrefUtil {
    private static final String PREF_SETTINGS_LANGUAGE = "pref_settings_language";
    public static String getLocale(Context context){
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

        String loadLanguage = sharedPreferences.getString(PREF_SETTINGS_LANGUAGE, "");
        Log.d("LoadLanguage", loadLanguage);
        return loadLanguage;
    }
}

MainActivity.java 设置语言环境,我输入了 onCreate 和 onResume

private void appLocale(String localeCode){
        Locale locale = new Locale(localeCode);
        Locale.setDefault(locale);
        Configuration configuration = getBaseContext().getResources().getConfiguration();
        configuration.locale = locale;
        getBaseContext().getResources().updateConfiguration(configuration, getBaseContext().getResources().getDisplayMetrics());
    }

在 activity class 中,您应该覆盖 attachBaseContext(base : Context).

创建摘要 class BaseActivity 并在 MainActivity 上扩展它。

通过这样做,您不必在每个 activity class 中写 onAttachBaseContext(),但应该扩展 BaseActivity 而不是 AppCompatActivity

class BaseActivity : AppCompatActivity {

    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(LocaleHelper.onAttach(base))
    }
}

要保留语言设置,您还应该覆盖应用程序 class 中的 attachBaseContext(base:Context)

class App : Application() {

   override fun attachBaseContext(base: Context) {
        super.attachBaseContext(LocaleHelper.onAttach(base, LocaleHelper.LANG_EN))
    }
}

如果您需要本地化的帮手 class,这里就是。代码是 Kotlin 的,但我想你会明白的。

object LocaleHelper {

    private const val SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"

    const val LANG_EN = "en"
    const val LANG_ES = "es"

    val languageMap = hashMapOf(
        LANG_EN to "English",
        LANG_ES to "Spanish"
    )

    fun onAttach(context: Context): Context {
        val lang = getPersistedData(context, Locale.getDefault().language)
        return setLocale(context, lang)
    }

    fun onAttach(context: Context, defaultLanguage: String): Context {
        val lang = getPersistedData(context, defaultLanguage)
        return setLocale(context, lang)
    }

    fun getLanguage(context: Context): String? {
        return getPersistedData(context, Locale.getDefault().language)
    }

    fun setLocale(context: Context, language: String?): Context {
        persist(context, language)
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            updateResources(context, language)
        } else {
            updateResourcesLegacy(context, language)
        }

    }

    private fun getPersistedData(context: Context, defaultLanguage: String): String? {
        val preferences = PreferenceManager.getDefaultSharedPreferences(context)
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage)
    }

    private fun persist(context: Context, language: String?) {
        val preferences = PreferenceManager.getDefaultSharedPreferences(context)
        val editor = preferences.edit()

        editor.putString(SELECTED_LANGUAGE, language)
        editor.apply()
    }

    @TargetApi(Build.VERSION_CODES.N)
    private fun updateResources(context: Context, language: String?): Context {
        val locale = Locale(language)
        Locale.setDefault(locale)

        val configuration = context.resources.configuration
        configuration.setLocale(locale)
        configuration.setLayoutDirection(locale)

        return context.createConfigurationContext(configuration)
    }

    // used for api level < 24
    @Suppress("DEPRECATION")
    private fun updateResourcesLegacy(context: Context, language: String?): Context {
        val locale = Locale(language)
        Locale.setDefault(locale)
        val resources = context.resources
        val configuration = resources.configuration
        configuration.locale = locale
        resources.updateConfiguration(configuration, resources.displayMetrics)
        return context
    }
}