Идентификация языка RTL в Android

Есть ли способ идентифицировать язык RTL (справа налево), помимо проверки кода языка на всех языках RTL?

Поскольку API 17+ позволяет несколько ресурсов для RTL и LTR, я полагаю, должен быть способ, по крайней мере, от API 17.

Получите его из Configuration.getLayoutDirection () :

Configuration config = getResources().getConfiguration(); if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { //in Right To Left layout } 

Ответ @ cyanide имеет правильный подход, но критическая ошибка.

Character.getDirectionality возвращает двунаправленный (bidi) тип символа . Текст слева направо – предсказуемый тип L, а справа налево также предсказуемо тип R. BUT, арабский текст возвращает другой тип, тип AL.

Я добавил проверку как для типа R, так и для типа AL, а затем вручную проверил каждый RTL-язык Android, в который входят: иврит (Израиль), арабский (Египет) и арабский (Израиль).

Как вы можете видеть, это оставляет в стороне другие права налево, поэтому я был обеспокоен тем, что, когда Android добавит эти языки, может возникнуть аналогичная проблема, и вы не заметите ее сразу.

Поэтому я тестировал вручную каждый RTL-язык.

  • Арабский (العربية) = тип AL
  • Курдский (کوردی) = тип AL
  • Фарси (فارسی) = тип AL
  • Урду (اردو) = тип AL
  • Иврит (עברית) = тип R
  • Идиш (ייִדיש) = тип R

Таким образом, похоже, что это должно отлично работать:

 public static boolean isRTL() { return isRTL(Locale.getDefault()); } public static boolean isRTL(Locale locale) { final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0)); return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; } 

Спасибо @cyanide за отправку меня в правильном направлении!

Если вы используете библиотеку поддержки, вы можете сделать следующее:

 if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) { // The view has RTL layout } else { // The view has LTR layout } 

Существует очень простой способ проверить направление макета представления, но он возвращается к LTR на устройствах с предварительным интерфейсом API 17:

 ViewUtils.isLayoutRtl(View view); 

class ViewUtils поставляется в комплекте с библиотекой поддержки v7, поэтому он должен быть уже доступен, если вы используете библиотеку appcompat.

Вы можете использовать TextUtilsCompat из библиотеки поддержки.

TextUtilsCompat.getLayoutDirectionFromLocale(locale)

Я собрал много информации и, наконец, сделал свой, надеюсь, полный class RTLUtils.

Это позволяет узнать, является ли данный Locale или View «RTL» 🙂

 package com.elementique.shared.lang; import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Set; import android.support.v4.view.ViewCompat; import android.view.View; public class RTLUtils { private static final Set RTL; static { Set lang = new HashSet(); lang.add("ar"); // Arabic lang.add("dv"); // Divehi lang.add("fa"); // Persian (Farsi) lang.add("ha"); // Hausa lang.add("he"); // Hebrew lang.add("iw"); // Hebrew (old code) lang.add("ji"); // Yiddish (old code) lang.add("ps"); // Pashto, Pushto lang.add("ur"); // Urdu lang.add("yi"); // Yiddish RTL = Collections.unmodifiableSet(lang); } public static boolean isRTL(Locale locale) { if(locale == null) return false; // Character.getDirectionality(locale.getDisplayName().charAt(0)) // can lead to NPE (Java 7 bug) // https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab // using hard coded list of locale instead return RTL.contains(locale.getLanguage()); } public static boolean isRTL(View view) { if(view == null) return false; // config.getLayoutDirection() only available since 4.2 // -> using ViewCompat instead (from Android support library) if (ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL) { return true; } return false; } } 

Наслаждаться 🙂

Вы можете проверить это, если хотите проверить API ниже 17

 boolean isRightToLeft = TextUtilsCompat.getLayoutDirectionFromLocale(Locale .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; 

ИЛИ для API 17 или выше

 boolean isRightToLeft = TextUtils.getLayoutDirectionFromLocale(Locale .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; 

Для более точного контроля над пользовательским интерфейсом вашего приложения в режиме LTR и RTL, Android 4.2 включает в себя следующие новые API-интерфейсы, которые помогут управлять компонентами View:

 android:layoutDirection — attribute for setting the direction of a component's layout. android:textDirection — attribute for setting the direction of a component's text. android:textAlignment — attribute for setting the alignment of a component's text. getLayoutDirectionFromLocale() — method for getting the Locale-specified direction 

Таким образом getLayoutDirectionFromLocale () должен помочь вам. См. Пример кода здесь: https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java

Спасибо всем.

Если вы посмотрите на код LayoutUtil.getLayoutDirectionFromLocale() (и, я полагаю, Confuiguration.getLayoutDirection() ), он заканчивает анализом стартовой буквы отображаемого имени локали, используя Character.getDirectionality .

Поскольку Character.getDirectionality был примерно с Android 1, следующий код будет совместим со всеми релизами Android (даже те, которые не поддерживают RTL правильно :)):

 public static boolean isRTL() { return isRTL(Locale.getDefault()); } public static boolean isRTL(Locale locale) { return Character.getDirectionality(locale.getDisplayName().charAt(0)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT; } 

При создании библиотеки вам также всегда нужно проверить, поддерживает ли приложение RTL, используя

 (getApplicationInfo().flags &= ApplicationInfo.FLAG_SUPPORTS_RTL) != 0 

Когда приложение работает в локали RTL, но оно не объявлено в манифесте android:supportsRtl="true" тогда он работает в режиме LTR.

Это будет работать во всех SDKS:

 private boolean isRTL() { Locale defLocale = Locale.getDefault(); return Character.getDirectionality(defLocale.getDisplayName(defLocale).charAt(0)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT; } 

Просто используйте этот код:

  public static boolean isRTL() { return isRTL(Locale.getDefault()); } public static boolean isRTL(Locale locale) { final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0)); return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; } if (isRTL()) { // The view has RTL layout } else { // The view has LTR layout } 

Это будет работать для всех приложений Android API.

Поддержка родного RTL в Android 4.2

  public static ComponentOrientation getOrientation(Locale locale) { // A more flexible implementation would consult a ResourceBundle // to find the appropriate orientation. Until pluggable locales // are introduced however, the flexiblity isn't really needed. // So we choose efficiency instead. String lang = locale.getLanguage(); if( "iw".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang) ) { return RIGHT_TO_LEFT; } else { return LEFT_TO_RIGHT; } } 

Поскольку устройства на английском языке поддерживают RTL, вы можете использовать этот код в своем MainActivity для изменения языка устройства на английском языке, и вам не нужно «поддерживать RTL».

 String languageToLoad = "en"; // your language Locale locale = new Locale(languageToLoad); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); 
  • Получить программную модель Android Phone
  • Как установить layout_gravity программно?
  • Android: Как создавать звуковые эффекты fade-in / fade-out для любого музыкального файла, который играет мое приложение?
  • Выключить автозапуск для EditText?
  • Подсчет голосов в EditText Changed Listener
  • Почему автоматически добавляются разрешения на мой AndroidManifest при включении библиотеки Google Play Services
  • fragment жизненного цикла: когда «ondestroy» и «ondestroyview» не называются?
  • Android Studio не удается отладить с ошибкой org.gradle.process.internal.ExecException
  • Значок панели уведомлений становится белым в Android 5 Lollipop
  • Пользовательские макеты уведомлений и цвета текста
  • Активность Android как диалог
  • Давайте будем гением компьютера.