Identificando el lenguaje RTL en Android
right-to-left (14)
¿Hay alguna forma de identificar el lenguaje RTL (de derecha a izquierda), además de probar el código de idioma en todos los idiomas RTL?
Dado que API 17+ permite varios recursos para RTL y LTR, supongo que debería haber una forma, al menos desde API 17.
Al crear una biblioteca, siempre debe comprobar si la aplicación admite RTL utilizando
(getApplicationInfo().flags &= ApplicationInfo.FLAG_SUPPORTS_RTL) != 0
Cuando la aplicación se ejecuta en la configuración regional de RTL, pero no se declara en el manifiesto de android:supportsRtl="true"
entonces se ejecuta en modo LTR.
Debido a que los dispositivos de idioma inglés son compatibles con RTL, puede usar este código en MainActivity para cambiar el idioma del dispositivo a inglés y no necesita el código "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());
Esto funcionará en todos los SDKS:
private boolean isRTL() {
Locale defLocale = Locale.getDefault();
return Character.getDirectionality(defLocale.getDisplayName(defLocale).charAt(0)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT;
}
Gracias a todos.
Si observa el código de LayoutUtil.getLayoutDirectionFromLocale()
(y, supongo que Confuiguration.getLayoutDirection()
también) termina analizando la letra inicial del nombre para mostrar la configuración regional, usando Character.getDirectionality
.
Dado que Character.getDirectionality
existía desde Android 1, el siguiente código será compatible con todas las versiones de Android (incluso aquellas que no admiten RTL correctamente :)):
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;
}
Hay una forma realmente sencilla de verificar la dirección de diseño de una vista, pero recurre a LTR en los dispositivos anteriores a la API 17:
ViewUtils.isLayoutRtl(View view);
La clase ViewUtils viene con la biblioteca de soporte v7, por lo que ya debería estar disponible si está utilizando la biblioteca appcompat.
La respuesta de @cianuro tiene el enfoque correcto pero un error crítico.
Character.getDirectionality devuelve el tipo de carácter bidireccional (bidi) . El texto de izquierda a derecha es un tipo predecible L y de derecha a izquierda también es predecible el tipo R. PERO, el texto en árabe devuelve otro tipo, el tipo AL.
Agregué un cheque para el tipo R y el tipo AL y luego probé manualmente cada idioma RTL con Android: hebreo (Israel), árabe (Egipto) y árabe (Israel).
Como puede ver, esto deja de lado otros idiomas de derecha a izquierda, por lo que me preocupaba que a medida que Android agregue estos idiomas, podría haber un problema similar y uno podría no darse cuenta de inmediato.
Así que probé manualmente cada lenguaje RTL.
- Árabe (العربية) = tipo AL
- Kurdo (وردی) = tipo AL
- Farsi (فارسی) = tipo AL
- Urdu (اردو) = tipo AL
- Hebreo (hebreo) = tipo R
- Yiddish (ייִדיש) = tipo R
Así que parece que esto debería funcionar muy bien:
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;
}
Gracias @cyanide por enviarme la dirección correcta!
Obtenlo de Configuration.getLayoutDirection() :
Configuration config = getResources().getConfiguration();
if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
//in Right To Left layout
}
Para un control más preciso sobre la IU de su aplicación en modo LTR y RTL, Android 4.2 incluye las siguientes nuevas API para ayudar a administrar los componentes de 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
Por lo tanto, getLayoutDirectionFromLocale () debería ayudarlo. Consulte el código de muestra aquí: https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java
Puede usar TextUtilsCompat desde la biblioteca de soporte.
TextUtilsCompat.getLayoutDirectionFromLocale(locale)
Puede verificar de esta forma si desea verificar que la API sea inferior a 17
boolean isRightToLeft = TextUtilsCompat.getLayoutDirectionFromLocale(Locale
.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
O para API 17 o superior
boolean isRightToLeft = TextUtils.getLayoutDirectionFromLocale(Locale
.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
Recolecté mucha información y finalmente hice mi propia clase de RTLUtils, con suerte completa.
Permite saber si una configuración regional o vista dada es ''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;
}
}
Disfruta :-)
Si está utilizando la biblioteca de soporte, puede hacer lo siguiente:
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) {
// The view has RTL layout
} else {
// The view has LTR layout
}
Solo usa este código:
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
}
Esto funcionará para todos los niveles de API de Android.
Soporte RTL nativo en 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;
}
}