我想在我的Android项目中使用复数形式。但是,我提供的值可以是浮点值。
因此,例如,当设置1.5星时,我想要理解,它不是1星而是1.5星。
<plurals name="stars">
<item quantity="one">%d star</item>
<item quantity="other">%d stars</item>
</plurals>
但是,Android系统似乎只使用整数值(%d)。
该方法如下所示:
String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
其中数量定义为Int。
这有什么解决方案吗?
首先我要说:非常有趣的问题。
其次,这是解决方案:使用%s而不是%d作为占位符。
<plurals name="stars">
<item quantity="one">%s star</item>
<item quantity="other">%s stars</item>
</plurals>
那么你必须在数量上使用Math.ceil()
。所以1.1f
例如会变成2
,因此你的文字会从星星变成星星。
我在Kotlin和Java中编写了这个解决方案。
对于Kotlin,我写了一个扩展函数,如下所示:
fun Resources.getQuantityString(@PluralsRes pluralResId: Int, pluralValue: Float) =
this.getQuantityString(R.plurals.stars, Math.ceil(pluralValue.toDouble()).toInt(), pluralValue)
这将被称为:tvText.text = resources.getQuantityString(R.plurals.stars, 1.1f)
对于Java,我的解决方案如下所示:
import android.content.res.Resources;
import android.support.annotation.PluralsRes;
public class PluralResource {
public static String get(Resources resources, @PluralsRes int pluralResId, float pluralValue) {
return resources.getQuantityString(pluralResId, (int) Math.ceil(pluralValue), pluralValue);
}
}
这被称为:
tvText.text = PluralResource.get(resources, R.plurals.stars, 1.1f)
只需这样做:
getQuantityString(R.plurals.stars, quantity > 1f ? 2 : 1, quantity):
并用%f替换字符串中的%d。
经过进一步研究后,似乎没有好的解决方案。
正如在其他答案中看到的那样,它们总是需要大量的“手动处理”,而不需要创建单独的字符串资源。
一般建议似乎是手动舍入/处理浮点值(例如,检查浮点值是否匹配1.0),然后对复数调用使用适当的Int值。
但除了没有真正使用复数之外,这还伴随着其他语言的问题(例如,我不知道1.5星也会在另一种语言中复数,因为它是英语),因此这些舍入选项可能不适用于普遍。
所以答案是:似乎没有完美的解决方案(意思是由Android系统“自动”解决)。
因此我实际上只是选择异常并在那里使用不同的字符串。所以(伪代码)的做法目前看起来像
// optionally wrap different languages around
// if language == English
when (amountStars) {
is 1.0 -> getString(R.string.stars_singular, 1)
... ->
else -> getString(R.string.stars_plural, amountStars)
}
// if language == Chinese ...
其他案件必须“硬编码”。因此,例如,你必须决定0是否意味着
“0星”(复数串)或
“没有明星”(单数字符串)
但是,对于使用共同占位符的单独字符串资源,使用复数似乎没有任何实际好处。另一方面,这(对我而言)为格式化选项提供了更大的灵活性。例如,人们可以创建一个像“1星半”的文本,它再次成为单数(尽管在数字上我们会写1.5星)。