Использовать locale (ltr/rtl) для гравитации в TextView

У меня есть простой TextView, который должен иметь android:gravity="left" для локальных систем ltr и android:gravity="right" для локальных систем rtl.

Очевидным выбором будет: android:gravity="start", но затем, например, английский текст всегда будет выровнен по левому краю и выравнивается по иврите.

Вот как это выглядит с помощью android:gravity="start":

Локаль LTR:

|          לורם|   // incorrect
|test           |  // correct

Язык RTL:

|          לורם|  // correct
|test           |  // incorrect

он должен выглядеть так:

Локаль LTR:

|לורם           |  
|test            | 

Язык RTL:

|          לורם|  
|           test| 

Можно ли это сделать без использования папки layout-ldrtl с измененным XML файлом? Это усложняло бы развитие, потому что мне пришлось бы редактировать много файлов макета дважды...

edit: достаточно решение для API 17+. Я написал системный язык, но на самом деле я разрешаю пользователю изменять язык приложения следующим образом:

Configuration configuration = context.getResources().getConfiguration();
configuration.setLayoutDirection(selectedLocale);
configuration.locale = selectedLocale;
context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics());

поэтому было бы здорово, если бы этот язык был рассмотрен для выбора rtl ↔ ltr.

Ответ 1

Я использую это решение сейчас, я бы предпочел простое xml-решение, но это покажется минимальным:

if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
  if (DynamicLanguage.getLayoutDirection(getContext()) == View.LAYOUT_DIRECTION_RTL) {
    this.textView.setGravity(Gravity.RIGHT);
  } else {
    this.textView.setGravity(Gravity.LEFT);
  }
}

Ответ 2

У меня тоже была эта проблема, вы можете использовать эти свойства с помощью TextView

android:textDirection="locale"
android:textAlignment="gravity"

или просто добавьте его в базовую тему приложения в styles.xml `

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:textColorPrimary">@android:color/white</item>
    <item name="android:textColorSecondary">@android:color/white</item>
    <item name="colorButtonNormal">@color/colorAccent</item>
    <item name="android:textAlignment">gravity</item>
    <item name="android:textDirection">locale</item>
    </style>`

Это сработало для меня.

Ответ 3

android:layout_width="match_parent"    
android:textAlignment="viewStart"

Если текстовое представление растянуто до ширины родителя, нет необходимости изменять силу тяжести элемента. Просто выровняйте текст до начала просмотра, текст переместится в положение LTR или RTL, независимо от текстового содержимого (иврит или западное).

Ответ 4

Для этого вам, вероятно, нужен специальный расширенный класс TextView:

public class LocaleAwareTextView extends TextView {
    public LocaleAwareTextView(Context context) {
        super(context);
        setGravity(getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? Gravity.RIGHT : Gravity.LEFT);
    }
    public LocaleAwareTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setGravity(getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? Gravity.RIGHT : Gravity.LEFT);
    }

    public LocaleAwareTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setGravity(getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? Gravity.RIGHT : Gravity.LEFT);
    }

}

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