Changing app locale sometimes doesn't change direction of layouts
Asked Answered
G

1

2

I'm changing locale of my app programmatically using the following method. It works fine but when I start an already existing singleTask activity using Intent.FLAG_ACTIVITY_CLEAR_TOP flag. Then application loses the layout direction but translation is correct. For example, if application language is Arabic then all views direction is changed to English locale (left-to-right). What could be the reason?

I'm calling following method in attachBaseContext of BaseActivity and Application class.

public Context createLocaleConfiguration(Context context,String language) {
   
        Locale newLocale = new Locale(language);
        Resources res = context.getResources();
        Configuration configuration = res.getConfiguration();

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {
            LocaleList localeList = new LocaleList(newLocale);
            LocaleList.setDefault(localeList);
            configuration.setLocales(localeList);
            configuration.setLayoutDirection(newLocale);
            context = context.createConfigurationContext(configuration);

        } else {
            configuration.setLocale(newLocale);
            configuration.setLayoutDirection(configuration.locale);
            Locale.setDefault(newLocale);
            context = context.createConfigurationContext(configuration);
        }
        return context;
    }


@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(LocaleManager.getInstance().createLocaleConfiguration(newBase,language));
}

Any ideas would be appreciable. Thanks

Gagarin answered 8/7, 2020 at 5:23 Comment(0)
U
0

I guess you should try to use some helper class like this one:

public class LocaleHelper {

    private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";

    public static Context onAttach(Context context) {
        String lang = getPersistedData(context, Locale.getDefault().getLanguage());
        return setLocale(context, lang);
    }

    public static Context onAttach(Context context, String defaultLanguage) {
        String lang = getPersistedData(context, defaultLanguage);
        return setLocale(context, lang);
    }

    public static String getLanguage(Context context) {
        return getPersistedData(context, Locale.getDefault().getLanguage());
    }

    public static Context setLocale(Context context, String language) {
        persist(context, language);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return updateResources(context, language);
        }

        return updateResourcesLegacy(context, language);
    }

    private static String getPersistedData(Context context, String defaultLanguage) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
    }

    private static void persist(Context context, String language) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = preferences.edit();

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

    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Configuration configuration = context.getResources().getConfiguration();
        configuration.setLocale(locale);
        configuration.setLayoutDirection(locale);

        return context.createConfigurationContext(configuration);
    }

    private static Context updateResourcesLegacy(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);

        Resources resources = context.getResources();

        Configuration configuration = resources.getConfiguration();
        configuration.locale = locale;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale);
        }

        resources.updateConfiguration(configuration, resources.getDisplayMetrics());

        return context;
    }
}

And than just use it in you application and base activity classes like that:

  override fun attachBaseContext(newBase: Context?) {
        super.attachBaseContext(LocaleHelper.onAttach(newBase))
    }
Urn answered 8/7, 2020 at 6:5 Comment(5)
I've written a helper class but didn't post here complete code to not make it messy. Just posted important piece of code. Besides that code is same.Gagarin
Do you recreate your activities after lang change?Urn
Yes, and even if app is killed and started again it works until the scenario mentioned in question happens.Gagarin
So do you recreate it in onNewIntent() after that scenario?Urn
No, if I had to recreate in onNewIntent then what was the purpose of calling it this way.Gagarin

© 2022 - 2024 — McMap. All rights reserved.