Is there a way to identify RTL (right-to-left) language, apart from testing language code against all RTL languages?
Since API 17+ allows several resources for RTL a
For more precise control over your app UI in both LTR and RTL mode, Android 4.2 includes the following new APIs to help manage View components:
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
Thus getLayoutDirectionFromLocale() should help you out. Refer the sample code here : https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java
When building library you also always need to check if application is supporting RTL by using
(getApplicationInfo().flags &= ApplicationInfo.FLAG_SUPPORTS_RTL) != 0
When application is running on RTL locale, but it isn't declared in manifest android:supportsRtl="true"
then it is running in LTR mode.
Thanks to all.
If you look at the code of LayoutUtil.getLayoutDirectionFromLocale()
(and, I assume Confuiguration.getLayoutDirection()
as well), it ends up with analysing the starting letter of locale display name, using Character.getDirectionality
.
Since Character.getDirectionality
was around from Android 1, the following code will be compatible with all Android releases (even those, not supporting RTL correctly :)):
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;
}
You can detect if a string is RTL/LTR with Bidi. Example:
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
}
I gathered many information and finally made my own, hopefully complete, RTLUtils class.
It allows to know if a given Locale or View is '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;
}
}
Easily you can use this :
if (getWindow().getDecorView().getLayoutDirection()== View.LAYOUT_DIRECTION_RTL) {
// The view has RTL layout
} else {
// The view has LTR layout
}