本文章翻译自Android开发指导,介绍了如何对字符串资源进行格式化和设置不同的样式。
想看原文,请戳这里
字符串资源的格式化和样式
小心撇号和引用号的坑
如果我们的字符串资源里面有撇号(‘),那么我们必须加上转移字符,变成这个样子(\’),或者是在字符串的外面包裹上一对引号。我们下面看个例子:
This\'ll work
"This'll also work"
This doesn't work
如果你的字符串有双引号,那么你必须用(\”)代替。在字符串外面包裹单引号是没有作用的。This is a \"good string\".
This is a "bad string".
'This is another "bad string".'
格式化字符串
如果你需要用 String.format(String, Object…) 这种方式来格式化字符串,那么你可以把你的格式化参数放在string的资源文件里面,我们以下面的这个资源举个例子:Hello, %1$s! You have %2$d new messages.
在上面这个例子里面,有两个格式化参数,%1s是一个字符串参数,d 是一个小数参数。你可以像下面这样格式化字符串:Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
用HTML添加样式
你可以使用HTML标签为你的字符串添加样式,下面我们举个例子:<?xml version="1.0" encoding="utf-8"?>
Welcome to Android!
支持的HTML元素标签包括:粗体字
斜体字
下划线
有些时候,你可能想创建即带有格式化参数,又可以格式化样式的字符串资源,通常来说,这不会起作用,因为直接使用
String.format(String, Object…)
会把所有的样式信息全部过滤掉。所以在格式化之后,需要用Html.fromHtml()把HTML标签的饿效果显示出来:存储样式文本为HTML转义字符串
Hello, %1$s! You have %2$d new messages.
在这个格式化字符串里面,标签被添加进去了。注意左括号被HTML转义字符串 < 代替了。这样格式化字符串就和普通的一样了,但是我们还需要调用Html.fromHtml()把HTML标签转换成样式文本Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
CharSequence styledText = Html.fromHtml(text);
因为Html.fromHtml()会把所有的HTML实体都格式化了,所以一定要把字符串进行格式化,避免出现任何可能的HTML字符,可以使用
TextUtil.htmlEncode(username)完成。比如说,如果你要给 String.format()
传递一个带有”
Html.fromHtml(text)之后,这样字符就会按照一开始写进去的那样显示出来了。我们举个例子:String escapedUsername = TextUtil.htmlEncode(username);
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), escapedUsername, mailCount);
CharSequence styledText = Html.fromHtml(text);用Spannables设置样式
使用Spannables对象,我们可以设置字体的颜色和字体大小。你可以使用SpannableStringBuilder来创建自己的文本,然后使用android.text.style包里面的类,将样式应用起来。
我们可以使用下面的帮助方法,完成创建spannable文本的大部分工作/**
* Returns a CharSequence that concatenates the specified array of CharSequence
* objects and then applies a list of zero or more tags to the entire range.
*
* @param content an array of character sequences to apply a style to
* @param tags the styled span objects to apply to the content
* such as android.text.style.StyleSpan
*
*/
private static CharSequence apply(CharSequence[] content, Object... tags) {
SpannableStringBuilder text = new SpannableStringBuilder();
openTags(text, tags);
for (CharSequence item : content) {
text.append(item);
}
closeTags(text, tags);
return text;
}
/**
* Iterates over an array of tags and applies them to the beginning of the specified
* Spannable object so that future text appended to the text will have the styling
* applied to it. Do not call this method directly.
*/
private static void openTags(Spannable text, Object[] tags) {
for (Object tag : tags) {
text.setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK);
}
}
/**
* "Closes" the specified tags on a Spannable by updating the spans to be
* endpoint-exclusive so that future text appended to the end will not take
* on the same styling. Do not call this method directly.
*/
private static void closeTags(Spannable text, Object[] tags) {
int len = text.length();
for (Object tag : tags) {
if (len > 0) {
text.setSpan(tag, 0, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
text.removeSpan(tag);
}
}
}
下面这段代码演示了我们应该如何使用这些方法,来完成我们的效果,比如说粗体、斜体和颜色等。你也可以参考这种做法,来完成其他的文本样式/**
* Returns a CharSequence that applies boldface to the concatenation
* of the specified CharSequence objects.
*/
public static CharSequence bold(CharSequence... content) {
return apply(content, new StyleSpan(Typeface.BOLD));
}
/**
* Returns a CharSequence that applies italics to the concatenation
* of the specified CharSequence objects.
*/
public static CharSequence italic(CharSequence... content) {
return apply(content, new StyleSpan(Typeface.ITALIC));
}
/**
* Returns a CharSequence that applies a foreground color to the
* concatenation of the specified CharSequence objects.
*/
public static CharSequence color(int color, CharSequence... content) {
return apply(content, new ForegroundColorSpan(color));
}
下面的代码则演示了如何使用方法链来让个别的单词产生不同的文本样式:// Create an italic "hello, " a red "world",
// and bold the entire sequence.
CharSequence text = bold(italic(res.getString(R.string.hello)),
color(Color.RED, res.getString(R.string.world)));