Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Итак, я тестировал вручную каждый язык RTL.

  • Арабский (العربية) = тип AL
  • Курдский (کوردی) = тип AL
  • Farsi (فارسی) = тип 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 за отправку меня в правильном направлении!

Ответ 3

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

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

Ответ 4

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

TextUtilsCompat.getLayoutDirectionFromLocale(locale)

Ответ 5

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

ViewUtils.isLayoutRtl(View view);

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

Ответ 6

Я собрал много информации и, наконец, создал свой, надеюсь, завершенный класс 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<String> RTL;

    static
    {
        Set<String> lang = new HashSet<String>();
        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;
    }
}

Ответ 7

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

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

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

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

Ответ 8

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

android:layoutDirection — attribute for setting the direction of a component layout.
android:textDirection — attribute for setting the direction of a component text.
android:textAlignment — attribute for setting the alignment of a component 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

Ответ 9

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

Если вы посмотрите на код 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; 
}

Ответ 10

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

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

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

Ответ 11

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

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

Ответ 12

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

 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
 }

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

Ответ 13

Встроенная поддержка 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;
            }
    }

Ответ 14

Поскольку устройства на английском языке поддерживают 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());

Ответ 15

Вы можете определить, является ли строка RTL/LTR с помощью Bidi. Пример:

import java.text.Bidi;

Bidi bidi = new Bidi( title, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT );

if( bidi.isLeftToRight() ) {
   // it LTR
} else {
   // it RTL
}