简体   繁体   中英

Bug when formatting “%d - %d” in RTL on Samsung devices with Android 8.0

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);

Emulator screenshot: 在此输入图像描述

Samsung S7 screenshot: 在此输入图像描述

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.

add

     android:layoutDirection="rtl"

to your

    <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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM