将Spannable与String.format()组合 [英] Combining Spannable with String.format()
问题描述
假设您具有以下字符串:
Suppose you have the following string:
String s = "The cold hand reaches for the %1$s %2$s Ellesse's";
String old = "old";
String tan = "tan";
String formatted = String.format(s,old,tan); //"The cold hand reaches for the old tan Ellesse's"
假设您要以该字符串结尾,但是还具有特定的 Span
设置为用String.format
替换的任何单词.
Suppose you want to end up with this string, but also have a particular Span
set for any word replaced by String.format
.
例如,我们还想执行以下操作:
For instance, we also want to do the following:
Spannable spannable = new SpannableString(formatted);
spannable.setSpan(new StrikethroughSpan(), oldStart, oldStart+old.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ForegroundColorSpan(Color.BLUE), tanStart, tanStart+tan.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
是否有一种健壮的方法来了解old
和tan
的起始索引?
Is there a robust way of getting to know the start indices of old
and tan
?
请注意,仅搜索"old"会在"cold"中返回"old",因此将无法正常工作.
Note that just searching for 'old' returns the 'old' in 'cold', so that won't work.
会起作用的是事先搜索%[0-9]$s
,然后计算偏移量以解决String.format
中的替换问题.但是,这似乎让人头疼,我怀疑可能有一种类似String.format
的方法,它可以更详细地说明其格式.好吧,有吗?
What will work, I guess, is searching for %[0-9]$s
beforehand, and calculating the offsets to account for the replacements in String.format
. This seems like a headache though, I suspect there might be a method like String.format
that is more informative about the specifics of its formatting. Well, is there?
推荐答案
使用像这样的Spannables令人头疼-这可能是最简单的方法:
Using Spannables like that is a headache -- this is probably the most straightforward way around:
String s = "The cold hand reaches for the %1$s %2$s Ellesse's";
String old = "<font color=\"blue\">old</font>";
String tan = "<strike>tan</strike>";
String formatted = String.format(s,old,tan); //The cold hand reaches for the <font color="blue">old</font> <strike>tan</strike> Ellesse's
Spannable spannable = Html.fromHtml(formatted);
问题:这没有放在StrikethroughSpan
中.为了制作StrikethroughSpan
,我们从此问题.
Problem: this does not put in a StrikethroughSpan
. To make the StrikethroughSpan
, we borrow a custom TagHandler
from this question.
Spannable spannable = Html.fromHtml(text,null,new MyHtmlTagHandler());
MyTagHandler:
MyTagHandler:
public class MyHtmlTagHandler implements Html.TagHandler {
public void handleTag(boolean opening, String tag, Editable output,
XMLReader xmlReader) {
if (tag.equalsIgnoreCase("strike") || tag.equals("s")) {
processStrike(opening, output);
}
}
private void processStrike(boolean opening, Editable output) {
int len = output.length();
if (opening) {
output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK);
} else {
Object obj = getLast(output, StrikethroughSpan.class);
int where = output.getSpanStart(obj);
output.removeSpan(obj);
if (where != len) {
output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
private Object getLast(Editable text, Class kind) {
Object[] objs = text.getSpans(0, text.length(), kind);
if (objs.length == 0) {
return null;
} else {
for (int i = objs.length; i > 0; i--) {
if (text.getSpanFlags(objs[i - 1]) == Spannable.SPAN_MARK_MARK) {
return objs[i - 1];
}
}
return null;
}
}
}
这篇关于将Spannable与String.format()组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!