Android Layout Direction не обновляется при изменении языка во время выполнения

Я работаю над приложением, которое поддерживает два разных языка -

  1. английский
  2. арабский

Пользователь может переключиться на любой язык в любое время, и в зависимости от выбора я меняю язык приложения.

Ниже приведен фрагмент кода -

public static void setLocale(String languageCode, Context ctx) {

    Locale locale = new Locale(languageCode);
    Locale.setDefault(locale);

    if (Build.VERSION.SDK_INT >= VERSION_CODES.N) {
        updateResourcesLocale(ctx, locale);
    } else {
        updateResourcesLocaleLegacy(ctx, locale);
    }
}


private static void updateResourcesLocale(Context context, Locale locale) {
    Configuration configuration = context.getResources().getConfiguration();
    configuration.setLocale(locale);
    context.getApplicationContext().createConfigurationContext(configuration);
}

private static void updateResourcesLocaleLegacy(Context context, Locale locale) {
    Resources resources = context.getResources();
    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;
    configuration.setLayoutDirection(locale);
    resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}

Также во всех действиях приложения я переопределил метод attachBaseContext. Я использовал в нем ниже логику -

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(ContextWrapper.onAttach(base, LanguageUtil.getSelectedLanguageFromSharedPreferences(base)));
}

Это служебный класс -

public class ContextWrapper {

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

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

   private 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();
}

@TargetApi(Build.VERSION_CODES.N)
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);
}

@SuppressWarnings("deprecation")
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;

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

    return context;
}

Проблема в том, что если я переключусь на арабский язык, направление макета изменится на RTL, и это ожидается. Затем я снова переключаю свой язык на английский. Однако на этот раз направление макета не обновляется. Это все еще RTL, но должен быть LTR. На этом этапе, если я меняю язык на арабский, направление макета переходит в LTR, что снова неверно. Я добавил свойство ниже в тег приложения файла манифеста -

android:supportsRtl="true"

Кроме того, я заменил все выравнивание по левому краю на начало и выравнивание по правому краю к концу.

Во время отладки было замечено, что направление макета сохраняется правильно. Однако это не отражается в пользовательском интерфейсе.

My minSdkVersion 19 & targetSdkVersion 27

Я застрял в этом и не могу исправить эту проблему. Что мне здесь не хватает?


person Amrut    schedule 20.04.2018    source источник
comment
Возможно, этот вопрос поможет! Пожалуйста, прочтите его второй ответ, получивший только два голоса.   -  person Shubham Srivastava    schedule 20.04.2018
comment
Возникла такая же проблема, но ваше решение не сработало в моем случае. stackoverflow.com/q/62788071/5110536   -  person Usman Rana    schedule 08.07.2020


Ответы (1)


Наконец, после множества проб и ошибок я исправил эту проблему, добавив приведенный ниже код во все действия onCreate метод перед вызовом setContentView.

     if (BuildConfig.FLAVOR_country.equals("saudi") && "ar".equals(LanguageUtil.getSelectedLanguageFromSharedPreferences(this))) {
        getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
     } else {
        getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
    }
person Amrut    schedule 23.04.2018