Android mixed language text - BidiFormatter on String with RTL and LTR text
Asked Answered
D

4

10

I have a ListView with custom View where I have a TextView :

 <TextView
     android:id="@+id/textViewItemTitle"
     android:layout_width="0dp"
     android:layout_weight="1"
     android:layout_height="wrap_content"
     android:gravity="right|center_horizontal"
     android:text="title" />

This TextView contains Hebrew text.

 if(!bidi.isRtl(event)){
     event = bidi.unicodeWrap(event);
 }

 holder.title.setText(String.format("%s  %s  %s", bidi.unicodeWrap(item.getStartTimeNoDate().trim()), event,
 bidi.unicodeWrap(item.getDuration().trim())));

Where the first argument is time hh:mm:ss, second (event) is a Hebrew String and third like the first.

The problem: some time the event String contains mixed text in Hebrew and English like abc-אבג then all the text behave like the the gravity is left (and not right like I defined in the text view), I mean indented to left.

How to solve that?

Dickey answered 9/12, 2013 at 14:57 Comment(2)
Maybe you can post a screenshot to illustrate. Which system did you check? Implementations may be OEM-specific.Anywheres
Unfortunatly I cannot post a screenshot and I tested thta on several devices with different Android versionsDickey
C
13

Try adding to your TextView:

android:textDirection="anyRtl"

For more reading: http://developer.android.com/reference/android/view/View.html#attr_android:textDirection

Cornet answered 5/1, 2014 at 14:8 Comment(1)
android:textDirection can be used only for API level 17+.Frodine
B
17

The accepted answer will do the job when the text is in a TextView. This is a more general answer, applicable both to the basic/happy scenario and to other, more complicated use cases.

There are situations when mixed-language text is to be used someplace other than inside a TextView. For instance, the text may be passed in a share Intent to Gmail or WhatsApp and so on. In such cases, you must use a combination of the following classes:

As quoted in the documentation, these are ...

Utility class[es] for formatting text for display in a potentially opposite-directionality context without garbling. The directionality of the context is set at formatter creation and the directionality of the text can be either estimated or passed in when known.

So for example, say you have a String that has a combination of English & Arabic, and you need the text to be

  • right-to-left (RTL).
  • always right-aligned, even if the sentence begins with English.
  • English & Arabic words in the correct sequence and without garbling.

then you could achieve this using the unicodeWrap() method as follows:

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

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

This would convert the string into RTL and align it to the left, if even one RTL-language character was in the string, and fallback to LTR otherwise. If you want the string to be RTL even if it is completely in, say English (an LTR language), then you could use TextDirectionHeuristics.RTL instead of TextDirectionHeuristics.ANYRTL_LTR.

This is the proper way of handling mixed-direction text in the absence of a TextView. Interestingly, as the documentation states,

Also notice that these direction heuristics correspond to the same types of constants provided in the View class for setTextDirection(), such as TEXT_DIRECTION_RTL.

Update:

I just found the Bidi class in Java which seems to do something similar. Look it up!

Further references:

1. Write text file mix between arabic and english.

2. Unicode Bidirectional Algorithm.

Buzzard answered 15/11, 2016 at 5:38 Comment(0)
C
13

Try adding to your TextView:

android:textDirection="anyRtl"

For more reading: http://developer.android.com/reference/android/view/View.html#attr_android:textDirection

Cornet answered 5/1, 2014 at 14:8 Comment(1)
android:textDirection can be used only for API level 17+.Frodine
D
10

I had the same issue and I am targeting API 16 My solution was very simple, I added to the beginning of the String "\u200F"

String mixedLanguageText = ... // mixed-language text
newText = "\u200F" + mixedLanguageText;

"\u200F" = Unicode Character 'RIGHT-TO-LEFT MARK' (U+200F)

Demise answered 1/8, 2017 at 20:30 Comment(1)
solved the problem, but its have a conflict when using SpannableStringAqueduct
S
0

The following code snippet demonstrates how to use unicodeWrap():

String mySuggestion = "15 Bay Street, Laurel, CA";
BidiFormatter myBidiFormatter = BidiFormatter.getInstance();

// The "did_you_mean" localized string resource includes
// a "%s" placeholder for the suggestion.
String.format(R.string.did_you_mean,
        myBidiFormatter.unicodeWrap(mySuggestion));
Soracco answered 13/12, 2017 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.