【API Guides】Android字符串資源的格式化和樣式

轉載請註明出處:http://blog.csdn.net/zhaokaiqiang1992

本文章翻譯自Android開發指導,介紹瞭如何對字符串資源進行格式化和設置不同的樣式。
想看原文,請戳這裏

字符串資源的格式化和樣式

小心撇號和引用號的坑

如果我們的字符串資源裏面有撇號(‘),那麼我們必須加上轉移字符,變成這個樣子(\’),或者是在字符串的外面包裹上一對引號。我們下面看個例子:

<string name="good_example">This\'ll work</string>
<string name="good_example_2">"This'll also work"</string>
<string name="bad_example">This doesn't work</string>
    <!-- 會造成編譯錯誤 -->

如果你的字符串有雙引號,那麼你必須用(\”)代替。在字符串外面包裹單引號是沒有作用的。

<string name="good_example">This is a \"good string\".</string>
<string name="bad_example">This is a "bad string".</string>
    <!-- 引號會被忽略;最後的顯示結果就是: This is a bad string. -->
<string name="bad_example_2">'This is another "bad string".'</string>
    <!-- 會造成編譯錯誤 -->

格式化字符串

如果你需要用 String.format(String, Object…) 這種方式來格式化字符串,那麼你可以把你的格式化參數放在string的資源文件裏面,我們以下面的這個資源舉個例子:

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

在上面這個例子裏面,有兩個格式化參數,%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"?>
<resources>
    <string name="welcome">Welcome to <b>Android</b>!</string>
</resources>

支持的HTML元素標籤包括:

  • 粗體字
  • 斜體字
  • 下劃線

有些時候,你可能想創建即帶有格式化參數,又可以格式化樣式的字符串資源,通常來說,這不會起作用,因爲直接使用 String.format(String, Object…) 會把所有的樣式信息全部過濾掉。所以在格式化之後,需要用Html.fromHtml()把HTML標籤的餓效果顯示出來:

  • 存儲樣式文本爲HTML轉義字符串
<resources>
  <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
</resources>

在這個格式化字符串裏面,標籤被添加進去了。注意左括號被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)));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章