Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text direction change in a TextView when using LTR text in middle of RTL string

Our app supports different locals. There's a string with two replaceable values (money with currency symbol, USD$XXXXX ) in middle of that. But, when the locale is Arabic, there is strange behaviour. The direction of text changes when the text is more than one line. And only the texts on the first line is correct, while formatting on other lines get overridden by something!

As you can see in the screenshot, the green lines are correct as expected and the red ones are the wrong ones.

enter image description here

So far I have tried using:

  • BidFormatter
  • Unicode

The problem is that, after using the bidi format, the first number is correct but the second number is not.

And after using BidiFormat and unicode all the numbers are fine but, when the text is long and becomes multiple lines, only first line is correct and other lines are wrong again.

For unicode, I looked at : Unicode® Standard Annex #9 UNICODE BIDIRECTIONAL ALGORITHM (you can directly see this part if you are only interested in the main content)

You can take a look into this repo : Github Link

Here is the code I used for quick reference:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setTextViewTexts(R.id.tvLtrOneLine, formatWithCurrency(), R.string.text_short_english)
    setTextViewTexts(R.id.tvLtrTwoLines, formatWithCurrency(), R.string.text_long_english)
    setTextViewTexts(R.id.tvRtlOneLine, formatWithCurrency(), R.string.text_short_arabic)
    setTextViewTexts(R.id.tvRtlOneLineBidi, bidiFormatter(formatWithCurrency()), R.string.text_short_arabic)
    setTextViewTexts(R.id.tvRtlOneLineRtlFormatter, rtlMaker(formatWithCurrency()), R.string.text_short_arabic)
    setTextViewTexts(R.id.tvRtlTwoLines, formatWithCurrency(), R.string.text_long_arabic)
    setTextViewTexts(R.id.tvRtlTwoLinesBidi, bidiFormatter(formatWithCurrency()), R.string.text_long_arabic)
    setTextViewTexts(R.id.tvRtlTwoLinesRtlFormatter, rtlMaker(formatWithCurrency()), R.string.text_long_arabic)
}

private fun setTextViewTexts(textViewId: Int, text: String, stringResource: Int) {
    findViewById<TextView>(textViewId).text = getString(stringResource, text, text)
}

private fun formatWithCurrency(): String {
    val currency = "USD$"
    val price = 200
    val priceBuilder = StringBuilder("")
    priceBuilder.append(currency)
    priceBuilder.append(getDecimalFormattedPrice(price))
    return priceBuilder.toString()
}

private fun getDecimalFormattedPrice(price: Int): String {
    return DecimalFormat("0.00").format(price)
}

private fun rtlMaker(text: String): String {
    return "\u2066" + bidiFormatter(text) + "\u2069"
}

private fun bidiFormatter(text: String): String {
    return BidiFormatter.getInstance().unicodeWrap(text)
}

Is it an android bug or there is a workaround for that?

To see the bug, download the repository and run it on any device and change the device language to Arabic(Egypt)

EDIT: I submit the bug report

like image 526
Omid Heshmatinia Avatar asked Dec 05 '19 06:12

Omid Heshmatinia


1 Answers

@Omid Heshmatinia you can use spannableString or Html.fromHtml(string) it's give you more accurate output :)

like image 132
hio Avatar answered Oct 30 '22 13:10

hio