I have an app that supports RTL. When formatting a score between two teams I write something along the lines of:
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
Which outputs "0 - 1" on the Android emulator if my textfield is set to textDirection="locale", on all my test-devices running Android 8 and Android 9, on my Huawei and basically everywhere. But if I test this on a Samsung S7 with Android 8.0 it returns "1 - 0". I tested both on a physical device and on the device lab from Samsung: https://developer.samsung.com/remotetestlab/rtlDeviceList.action
Is this the wrong way of doing this? How can I format the score so it works on both LTR and RTL on all devices when I have a single text field containing the score? This works perfectly on most devices out there but I seem to be missing something in regards to why it breaks on Samsung devices.
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Home team won 1-0"/>
<TextView
android:id="@+id/t1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:text="1-0"
/>
<TextView
android:id="@+id/t2"
android:layoutDirection="rtl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:id="@+id/t3"
android:textDirection="locale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="rtl"
android:id="@+id/t4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="rtl"
android:id="@+id/t5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="locale"
android:id="@+id/t6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="locale"
android:id="@+id/t7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="locale"
android:id="@+id/t8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
<TextView
android:textDirection="locale"
android:id="@+id/t9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1-0"
/>
</LinearLayout>
App code:
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t2.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t3.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t4.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t5.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t6.setText(BidiFormatter.getInstance(Locale.forLanguageTag("ar-MA")).unicodeWrap(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0), TextDirectionHeuristicsCompat.ANYRTL_LTR));
t7.setText(BidiFormatter.getInstance(Locale.forLanguageTag("ar-MA")).unicodeWrap(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0), TextDirectionHeuristicsCompat.RTL));
t8.setText("\u200F" + String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
t9.setText("ع" + String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
setSupportActionBar(toolbar);
It seems this bug/feature on Samsung devices can in my case have a workaround:
String RTL_INDICATOR = "\u200f";
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d %s- %d", 1, RTL_INDICATOR, 0));
This Right-to-left-mark (https://www.fileformat.info/info/unicode/char/200f/index.htm) has to be inserted in the middle of the two integers. If inserted at the beginning of the string it doesn't resolve the issue.
The code gets pretty ugly as I have to do this in a number of places but it works on all devices across all Android versions (that I've tested) so marking this as the answer for now.