ITmob-Ly
发布于 2022-09-20 / 563 阅读
0

Android中的复数资源(数量字符串)和在 Compose 中对复数资源的支持

简介

Android 从 Android 1.0 就支持复数(数量字符串)。它是基于 XML 的资源,在 XML 文件中指定数量zeroonetwofewmany 和 other的值,并在代码中使用 getQuantityString() 方法获取语法正确的值。

选择使用哪一个字符串完全取决于语法上的必要性,如在中文中根本不做这些语法区分,因此获取的始终是 other 字符串,在英语中数量为 0,表示 zero 的字符串也会被忽略,因为在语法上,0 与 2 或除 1 以外的任何其他数字并无区别(“zero books” “one book” “two books”等)。

语法

XML 文件位置:res/values/filename.xml

文件名可以任意设置。<plurals> 元素的 name 用作资源的 ID。quantity 表示应在何时使用该字符串的值。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals
        name="plural_name">
        <item
            quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
            >text_string</item>
    </plurals>
</resources>

以下是关键字 quantity 的可用值的说明:

说明
zero当某种语言要求对数字 0(如阿拉伯语中的 0)进行特殊处理时。
one当某种语言要求对 1 这类数字(如英语和大多数其他语言中的数字 1;在俄语中,任何末尾为 1 但非 11 的数字均属此类)进行特殊处理时。
two当某种语言要求对 2 这类数字(如威尔士语中的 2,或斯洛文尼亚语中的 102)进行特殊处理时。
few当某种语言要求对“小”数字(如捷克语中的 2、3 和 4;或波兰语中末尾为 2、3 或 4,但非 12、13 或 14 的数字)进行特殊处理时。
many当某种语言要求对“大”数字(如马耳他语中末尾为 11 至 99 的数字)进行特殊处理时。
other当某种语言未要求对给定数量(如中文中的所有数字,或英语中的 42)进行特殊处理时。

示例:

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <item quantity="one">%d song found.</item>
        <item quantity="other">%d songs found.</item>
    </plurals>
</resources>

用法:

String songsFound = getResources().getQuantityString(R.plurals.numberOfSongsAvailable, count, count);
// 第一个 count 参数会选择合适的复数字符串,第二个 count 参数会插入 %d 占位符内。如果您的复数字符串没有字符串格式设置,则无需向 getQuantityString 传递第三个参数。

在 API 24 及更高级别的版本上,可以改为使用功能更强大的 ICU [MessageFormat](https://developer.android.com/reference/android/icu/text/MessageFormat) 类。

在 JetpackCompose 中使用复数资源

从 Compose 1.2 开始,我们可使用 pluralStringResource API 加载复数字符串。源码中该方法调用的是 getQuantityString 方法。

pluralStringResource(R.plurals.runtime_format, quantity, quantity)

目前的 Compose 版本(1.2.1)中它仍然是一个实验性的 API,所以需要添加注解:@ExperimentalComposeUiApi

这个方法在 Compose 1.2 之前的版本中不可用,可以继续使用 Android SDK 的 getQuantityString 方法。

LocalContext.current.resources.getQuantityString(R.plurals.runtime_format, quantity, quantity)

Compose 中是是怎样实现的

如下是源码中在 Compose 中添加对复数资源的支持的代码:

https://android-review.googlesource.com/c/platform/frameworks/support/+/1999932/3/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/StringResources.android.kt#80

/**
 * Load a plurals resource.
 *
 * @param id the resource identifier
 * @param count the count
 * @return the pluralized string data associated with the resource
 */
@Composable
@ReadOnlyComposable
fun pluralStringResource(@PluralsRes id: Int, count: Int): String {
    val resources = resources()
    return resources.getQuantityString(id, count)
}

/**
 * Load a plurals resource with provided format arguments.
 *
 * @param id the resource identifier
 * @param count the count
 * @param formatArgs arguments used in the format string
 * @return the pluralized string data associated with the resource
 */
@Composable
@ReadOnlyComposable
fun pluralStringResource(@PluralsRes id: Int, count: Int, vararg formatArgs: Any): String {
    val resources = resources()
    return resources.getQuantityString(id, count, *formatArgs)
}