在使用 Android 8.0 的三星设备上以 RTL 格式格式化“%d - %d”时出现错误
Bug when formatting "%d - %d" in RTL on Samsung devices with Android 8.0
我有一个支持 RTL 的应用程序。在格式化两个团队之间的分数时,我写了一些类似的东西:
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
如果我的文本字段设置为 textDirection="locale",则在 Android 模拟器上输出“0 - 1”,在我所有的测试设备上 运行 Android 8和Android9,在我的华为上基本上无处不在。但是如果我在 Android 8.0 的三星 S7 上测试它 returns “1 - 0”。我在三星的物理设备和设备实验室上进行了测试:https://developer.samsung.com/remotetestlab/rtlDeviceList.action
这是错误的做法吗?当我有一个包含乐谱的文本字段时,如何格式化乐谱以便它在所有设备上同时适用于 LTR 和 RTL?这在大多数设备上都能完美运行,但我似乎遗漏了一些关于它在三星设备上崩溃的原因。
这是我的代码:
<?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>
应用代码:
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);
模拟器截图:
三星S7截图:
添加
android:layoutDirection="rtl"
给你的
<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"
三星设备上的这个 bug/feature 在我的情况下似乎有一个解决方法:
String RTL_INDICATOR = "\u200f";
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d %s- %d", 1, RTL_INDICATOR, 0));
这个从右到左的标记(https://www.fileformat.info/info/unicode/char/200f/index.htm)必须插入到两个整数的中间。如果插入到字符串的开头,则无法解决问题。
代码变得非常丑陋,因为我必须在很多地方这样做,但它适用于所有 Android 版本(我已经测试过)的所有设备,所以暂时将其标记为答案.
我有一个支持 RTL 的应用程序。在格式化两个团队之间的分数时,我写了一些类似的东西:
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d - %d", 1, 0));
如果我的文本字段设置为 textDirection="locale",则在 Android 模拟器上输出“0 - 1”,在我所有的测试设备上 运行 Android 8和Android9,在我的华为上基本上无处不在。但是如果我在 Android 8.0 的三星 S7 上测试它 returns “1 - 0”。我在三星的物理设备和设备实验室上进行了测试:https://developer.samsung.com/remotetestlab/rtlDeviceList.action
这是错误的做法吗?当我有一个包含乐谱的文本字段时,如何格式化乐谱以便它在所有设备上同时适用于 LTR 和 RTL?这在大多数设备上都能完美运行,但我似乎遗漏了一些关于它在三星设备上崩溃的原因。
这是我的代码:
<?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>
应用代码:
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);
模拟器截图:
三星S7截图:
添加
android:layoutDirection="rtl"
给你的
<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"
三星设备上的这个 bug/feature 在我的情况下似乎有一个解决方法:
String RTL_INDICATOR = "\u200f";
t1.setText(String.format(Locale.forLanguageTag("ar-MA"), "%d %s- %d", 1, RTL_INDICATOR, 0));
这个从右到左的标记(https://www.fileformat.info/info/unicode/char/200f/index.htm)必须插入到两个整数的中间。如果插入到字符串的开头,则无法解决问题。
代码变得非常丑陋,因为我必须在很多地方这样做,但它适用于所有 Android 版本(我已经测试过)的所有设备,所以暂时将其标记为答案.