Полное решение этой проблемы состоит из трех этапов:
ШАГ 1 :
В onCreate()
ваших BaseActivity
(или всех ваших Activity
с) установите Locale
следующим образом:
@Override
protected void onCreate(Bundle savedInstanceState) {
// set the Locale the very first thing
Utils.setLocale(Utils.getSavedLocale());
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
......
......
}
, где getSavedLocale()
- это Locale
, соответствующий текущему региону (это будет характерно для вашего проекта ...).
А метод Utils.setLocale(...)
определяется следующим образом:
public static void setLocale(Locale locale){
Context context = MyApplication.getInstance();
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
Locale.setDefault(locale);
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
// updateConfiguration(...) is deprecated in N
if (Build.VERSION.SDK_INT >= 25) {
context = context.getApplicationContext().createConfigurationContext(configuration);
context = context.createConfigurationContext(configuration);
}
context.getResources().updateConfiguration(configuration,
resources.getDisplayMetrics());
}
Устанавливает правильные значения Locale
в каждом Activity
. Этого достаточно для приложений, поддерживающих уровень API 25. Для уровня API 26 и выше также требуются ШАГ 2 и ШАГ 3.
ШАГ 2 :
Переопределите следующий метод в вашем BaseActivity
:
@Override
protected void attachBaseContext(Context newBase) {
newBase = Utils.getLanguageAwareContext(newBase);
super.attachBaseContext(newBase);
}
где функция getLanguageAwareContext(...)
определяется следующим образом:
public static Context getLanguageAwareContext(Context context){
Configuration configuration = context.getResources().getConfiguration();
Locale locale = getIntendedLocale();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
Это, наряду с ШАГОМ 1, устанавливает правильные значения Locale
в каждом Activity
вашего приложения для API уровня 26 и выше.
Однако для правильной установки направления языка требуется еще один шаг ...
ШАГ 3 :
В onCreate()
вашего BaseActivity
добавьте следующий код:
@Override
protected void onCreate(Bundle savedInstanceState) {
....
....
// yup, it's a legit bug ... :)
if (Build.VERSION.SDK_INT >= 26) {
getWindow().getDecorView().setLayoutDirection(Utils.isRTL()
? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
}
....
....
}
где функция isRTL()
определяется следующим образом:
public static boolean isRTL(){
return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
}
Приведенные выше шаги должны решить все проблемы (по крайней мере, относительно установки Locale
и направления текста) во всех существующих версиях Android.