31

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"

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);

Is there a robust way of getting to know the start indices of old and tan?

Note that just searching for 'old' returns the 'old' in 'cold', so that won't work.

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?

4

5 に答える 5

17

スパンナブルで動作する のバージョンをString.format作成しました。通常版と同様にダウンロードしてご利用ください。あなたの場合、フォーマット指定子の周りにスパンを配置します(おそらくstrings.xmlを使用)。出力では、それらの指定子が置き換えられたものの周りになります。

于 2014-11-30T07:13:31.227 に答える
15

そのように Spannables を使用するのは頭痛の種です。これはおそらく最も簡単な方法です。

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習慣を借ります。TagHandler

Spannable spannable = Html.fromHtml(text,null,new MyHtmlTagHandler());

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;
        }
    }
}
于 2014-01-05T18:35:31.907 に答える