Android字符串资源的格式化和样式

ת×Ô£ºÕÔ¿­Ç¿µÄ²©¿Í

±¾ÎÄÕ·­Òë×ÔAndroid¿ª·¢Ö¸µ¼£¬½éÉÜÁËÈçºÎ¶Ô×Ö·û´®×ÊÔ´½øÐиñʽ»¯ºÍÉèÖò»Í¬µÄÑùʽ¡£
Ïë¿´Ô­ÎÄ£¬Çë´ÁÕâÀï

×Ö·û´®×ÊÔ´µÄ¸ñʽ»¯ºÍÑùʽ

СÐÄƲºÅºÍÒýÓúŵĿÓ

Èç¹ûÎÒÃǵÄ×Ö·û´®×ÊÔ´ÀïÃæÓÐƲºÅ(¡®)£¬ÄÇôÎÒÃDZØÐë¼ÓÉÏתÒÆ×Ö·û£¬±ä³ÉÕâ¸öÑù×Ó(\¡¯)£¬»òÕßÊÇÔÚ×Ö·û´®µÄÍâÃæ°ü¹üÉÏÒ»¶ÔÒýºÅ¡£ÎÒÃÇÏÂÃæ¿´¸öÀý×Ó£º

<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 <b>%2$d new messages</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() ´«µÝÒ»¸ö´øÓС±<¡±»òÕßÊÇ¡±&¡±ÕâÑùÀàËƵÄ×Ö·û£¬ÄÇôÔÚ¸ñʽ»¯Ö®Ç°£¬ÎÒÃDZØÐëÈ¥³ýµôÕâЩÌØÊâ·ûºÅ£¬ÕâÑùµ±ÎÒÃǰѸñʽ»¯ºÃµÄ×Ö·û´«µÝ¸ø 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)));