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"

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

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

мой minSdkVersion 19 & targetSdkVersion 27

Я застрял в этом и не могу решить эту проблему. Есть ли что-то, что я здесь скучаю?

2 ответа

Решение

Наконец, после множества проб и ошибок я исправил эту проблему, добавив приведенный ниже код во все действия метода 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);
    }

Добавьте этот код в верхний атрибут вашего макета.android:layoutDirection="locale"вместо добавления такого большого количества кода в ваш Java-файл

Другие вопросы по тегам