Как получить направление текста в Android и динамически менять раскладку в соответствии с направлением?

Я делаю некоторое исследование о возможности изменения пользовательского интерфейса динамически на основе направления текста. Хотя Google поддерживает языки RTL (ссылка: Поддержка родной RTL в Android 4.2), но она не охватывает ситуацию, когда приложение смешивает LTR и RTL.

Решение Google является правильным, если у нас есть многоязычное приложение, и у него разные источники статических данных (например, пункты меню) на разных языках. Тем не менее, я не нашел другого документа, касающегося того, как динамически изменять макет на основе направления текстового содержимого.

Следующее изображение показывает текущий дизайн моего тестового приложения. Список происходит из Facebook (список моих друзей) и содержит имена на английском и персидском языках.

enter image description here

Мое решение имеет два макета (один для LTR и один для RTL) в адаптере и назначение каждого из них в зависимости от направления имени. Итак, я написал следующие строки кода:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

            if(position % 2 == 0)
                convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
            else
                convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

            holder = new ViewHolder();

            holder.llSection = (LinearLayout) convertView.findViewById(R.id.section);
            holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
            holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
            holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);

            convertView.setTag(holder);



        holder.btnAdd.setTag(position);
        holder.tvUserName.setText(userList.get(position).getName());
        imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());

        ...

        return convertView;
    }

и результат:

enter image description here

Я зеркалировал строки на основе строки четной или нечетной. Теперь, мой вопрос заключается в том, как зеркалировать пользовательский интерфейс на основе имени. Я думаю, что я должен изменить условие условия от if(position % 2 == 0) на что-то вроде if(isNameLTR(FIRST_CHAR_OF_NAME)). Я не знаю, как реализовать этот метод.

Как я могу узнать, что символ LTR от RTL? (Я думаю, что Android знает, что первым символом слова является RTL или LTR, поэтому, когда ширина текстового представления соответствует родительскому, он выравнивает текст вправо, если символ RLT и слева, если символ LTR).

Любое предложение или комментарии будут оценены. Благодаря

Ответ 1

Решение, было легче, чем я думал:) Благодаря JAVA

Существует Bidi класс. Этот класс имеет метод getBaseLevel(), который возвращает 0, если ваш текст слева направо в противном случае 1 (если справа налево).

Итак, это мой код:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        if(bidi.getBaseLevel() == 0)
            convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
        else
            convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

...

и результат:

enter image description here

=============

Обновление

Существует другой метод baseIsLeftToRight(), который может быть лучше использован в инструкции if. Результат был таким же, как и выше.

Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
if(bidi.baseIsLeftToRight())
                convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
            else
                convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

Ответ 2

Используйте textAlignment с gravity, чтобы получить все тексты RIGHT или LEFT

android:gravity="right"
android:textAlignment="gravity"

Ответ 3

Если текст находится в TextView, тогда все, что вам нужно сделать, это

android:textDirection="anyRtl"

чтобы заставить RTL. См. Другие варианты для ваших требований.

Могут быть случаи, когда текст смешанного языка не должен отображаться в TextView. Например, текст может передаваться в share Intent в Gmail или WhatsApp и т.д. В таких случаях вы должны использовать комбинацию следующих классов:

Как указано в документации, это...

Класс полезности [es] для форматирования текста для отображения в потенциально противоположном контексте без искажения. Направленность контекста задается при создании форматирования, и направленность текста может быть оценена или передана, когда известна.

Итак, скажем, у вас есть String, который имеет комбинацию английского и арабского языков, и вам нужен текст

  • справа налево (RTL).
  • всегда выравнивание по правому краю, даже если предложение начинается с английского.
  • Английские и арабские слова в правильной последовательности и без искажений.

то вы можете достичь этого, используя метод unicodeWrap() следующим образом:

String mixedLanguageText = ... // mixed-language text

if(BidiFormatter.getInstance().isRtlContext()){
    Locale rtlLocale = ... // RTL locale
    mixedLanguageText = BidiFormatter.getInstance(rtlLocale).unicodeWrap(mixedLanguageText, TextDirectionHeuristics.ANYRTL_LTR);
}

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

Это правильный способ обработки текста смешанного текста в отсутствие TextView. Интересно, что, согласно документации,

Также обратите внимание, что эти эвристики направления соответствуют тем же типам констант, которые содержатся в классе View для setTextDirection(), например TEXT_DIRECTION_RTL.

Дополнительные ссылки:

1. Записать текстовый файл между арабским и английским.

2. Двунаправленный алгоритм Unicode.