如何在Android中使用格式化字符串和占位符?Kotlin 扩展函数

2022-08-31 14:23:44

在 Android 中,可以在字符串中使用占位符,例如:

<string name="number">My number is %1$d</string>

然后在 Java 代码中(在 以下子类中):Activity

String res = getString(R.string.number);
String formatted = String.format(res, 5);

甚至更简单:

String formatted = getString(R.string.number, 5);

也可以在 Android 字符串资源中使用一些 HTML 标记:

<string name="underline"><u>Underline</u> example</string>

由于本身不能保存有关格式的任何信息,因此应该使用方法代替方法:StringgetText(int)getString(int)

CharSequence formatted = getText(R.string.underline);

然后,返回的短语可以传递给 Android 小部件,例如 ,并且标记的短语将带有下划线。CharSequenceTextView

但是,我找不到如何将这两种方法组合在一起,将格式化字符串与占位符一起使用:

<string name="underlined_number">My number is <u>%1$d</u></string>

如何在Java代码中处理上述资源以,用整数代替它以显示它?TextView%1$d


答案 1

最后,我设法找到了一个可行的解决方案,并编写了自己的方法来替换占位符,保留格式:

public static CharSequence getText(Context context, int id, Object... args) {
    for(int i = 0; i < args.length; ++i)
        args[i] = args[i] instanceof String? TextUtils.htmlEncode((String)args[i]) : args[i];
    return Html.fromHtml(String.format(Html.toHtml(new SpannedString(context.getText(id))), args));
}

此方法不需要在格式化的字符串或替换占位符的字符串中手动转义 HTML 标记。


答案 2

Kotlin 扩展函数

  • 适用于所有 API 版本
  • 处理多个参数

用法示例

textView.text = context.getText(R.string.html_formatted, "Hello in bold")

包装在 CDATA 部分中的 HTML 字符串资源

<string name="html_formatted"><![CDATA[ bold text: <B>%1$s</B>]]></string>

结果

粗体文本:你好,粗体

法典

/**
* Create a formatted CharSequence from a string resource containing arguments and HTML formatting
*
* The string resource must be wrapped in a CDATA section so that the HTML formatting is conserved.
*
* Example of an HTML formatted string resource:
* <string name="html_formatted"><![CDATA[ bold text: <B>%1$s</B> ]]></string>
*/
fun Context.getText(@StringRes id: Int, vararg args: Any?): CharSequence =
    HtmlCompat.fromHtml(String.format(getString(id), *args), HtmlCompat.FROM_HTML_MODE_COMPACT)