web-dev-qa-db-ja.com

AndroidでRTL言語を識別する

すべてのRTL言語に対して言語コードをテストする以外に、RTL(右から左)言語を識別する方法はありますか?

API 17+ではRTLとLTRのいくつかのリソースが許可されているため、少なくともAPI 17からの方法があるはずです。

53
cyanide

Configuration.getLayoutDirection() から取得します。

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

@cyanideの答えには正しいアプローチがありますが、重大なバグがあります。

Character.getDirectionalityは、 双方向(双方向)文字タイプ を返します。左から右のテキストは予測可能なタイプLであり、右から左のテキストも予測可能なタイプRです。しかし、アラビア語のテキストは別のタイプ、タイプ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!

50
Tim Trueman

サポートライブラリを使用している場合は、次のことができます。

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

サポートライブラリの TextUtilsCompat を使用できます。

TextUtilsCompat.getLayoutDirectionFromLocale(locale)

13
Elyess Abouda

ビューのレイアウト方向を確認する非常に簡単な方法がありますが、API 17以前のデバイスではLTRにフォールバックします。

ViewUtils.isLayoutRtl(View view);

viewUtilsクラスはサポートv7ライブラリにバンドルされているため、appcompatライブラリを使用している場合は既に使用可能になっているはずです。

9
Johannes

私は多くの情報を収集し、最終的に私自身の、できれば完全なRTLUtilsクラスを作成しました。

特定のロケールまたはビューが「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;
    }
}
8
Pascal

17未満のAPIを確認する場合は、このように確認できます

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

またはAPI 17以上の場合

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

LTRモードとRTLモードの両方でアプリUIをより正確に制御するために、Android 4.2にはViewコンポーネントの管理に役立つ次の新しいAPIが含まれています。

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

3
SKN

ありがとうございます。

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; 
}
2
cyanide

ライブラリをビルドするときは、アプリケーションがRTLをサポートしているかどうかも常に確認する必要があります。

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

アプリケーションがRTLロケールで実行されているが、マニフェストで宣言されていない場合Android:supportsRtl="true"その後、LTRモードで実行されます。

2
Jedo

Bidi を使用すると、文字列がRTL/LTRであるかどうかを検出できます。例:

import Java.text.Bidi;

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

if( bidi.isLeftToRight() ) {
   // it's LTR
} else {
   // it's RTL
}
1
RonTLV

このコードを使用してください:

 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レベルで機能します。

1
Itiel Maimon

これはすべてのSDKSで機能します。

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

Android 4.2 でのネイティブRTLサポート

    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;
            }
    }
0
Amit Prajapati

英語のデバイスはRTLをサポートしているため、MainActivityでこのコードを使用してデバイスの言語を英語に変更できます。コードを「supportRTL」する必要はありません。

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());
0
Taha khozooie