How to use formatted strings together with placeholders in Android?
In Android it is possible to use placeholders in strings, such as:
<string name="number">My number is %1$d</string>
and then in Java code (inside a subclass of Activity
):
String res = getString(R.string.number);
String formatted = String.format(res, 5);
or even simpler:
String formatted = getString(R.string.number, 5);
It is also possible to use some HTML tags in Android string resources:
<string name="underline"><u>Underline</u> example</string>
Since the String
itself cannot hold any information about formatting, one should use getText(int)
instead of getString(int)
method:
CharSequence formatted = getText(R.string.underline);
The returned CharSequence
can be then passed to Android widgets, such as TextView
, and the marked phrase will be underlined.
However, I could not find how to combine these two methodes, using formatted string together with placeholders:
<string name="underlined_number">My number is <u>%1$d</u></string>
How to process above resource in the Java code to display it in a TextView
, substituting %1$d
with an integer?
Finally I managed to find a working solution and wrote my own method for replacing placeholders, preserving formatting:
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));
}
This approach does not require to escape HTML tags manually neither in a string being formatted nor in strings that replace placeholders.
Kotlin extension function that
- works with all API versions
- handles multiple arguments
Example usage
textView.text = context.getText(R.string.html_formatted, "Hello in bold")
HTML string resource wrapped in a CDATA section
<string name="html_formatted"><![CDATA[ bold text: <B>%1$s</B>]]></string>
Result
bold text: Hello in bold
Code
/**
* 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)
<resources>
<string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string>
</resources>
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
CharSequence styledText = Html.fromHtml(text);
More Infos here: http://developer.android.com/guide/topics/resources/string-resource.html