如何反转SpannableString中Span的优先级

6

在TextView中,添加到Spannable的span的优先级会影响其外观。当我们像下面这样向Spannable添加两个嵌套的Character Style时:

SpannableStringBuilder sp = new SpannableStringBuilder();
String blue = "blue";
String red = "red";
sp.append(blue);
sp.append(red);
sp.append(blue);
sp.setSpan(new ForegroundColorSpan(Color.RED), blue, 2*blue, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        
sp.setSpan(new ForegroundColorSpan(Color.BLUE), 0, sp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
((TextView)findViewById(R.id.text_view)).setText(sp);

添加字符样式的顺序对文本的外观非常重要。 在Android中,可以通过Spanned.SPAN_PRIORITY标记来处理跨度的优先级。但是当我们使用Html.fromHtml()时,优先级不在我们的掌握之中。所以我可以改变Html.fromHtml()输出的跨度优先级吗?或者我可以从中创建新的Spannable对象并设置新的跨度优先级;

2个回答

2
我为自己做了一个小技巧。它创建了一个新的可扩展Spannable,其中Spans是反转的。
final Spannable revertSpans(Spanned stext) {
    Object[] spans = stext.getSpans(0, stext.length(), Object.class);
    Spannable ret = Spannable.Factory.getInstance().newSpannable(stext.toString());
    if (spans != null && spans.length > 0) {
        for(int i = spans.length - 1; i >= 0; --i) {
            ret.setSpan(spans[i], stext.getSpanStart(spans[i]), stext.getSpanEnd(spans[i]), stext.getSpanFlags(spans[i]));
        }
    }

    return ret;
}

使用方法:

TextView tv = (TextView)finViewById(R.id.my_text_view);
Spanned stext = Html.fromHtml(text, null, myTagHandler);
Spannable sreverted = revertSpans(stext); 
tv.setText(sreverted);

也许这会有用。

0

你无法直接指定 Html.fromHtml() 的跨度优先级。相反,你可以从 Html.fromHtml() 返回的 Spanned 中调用 Spanned.getSpans() 方法来获取跨度对象。你可以使用 Spannable.setSpan() 方法将跨度复制到新的 Spannable 中,例如 SpannableStringBuilder

这是一个演示如何使用 Spanned.SPAN_PRIORITY_SHIFT 在其他跨度之前或之后应用一个跨度的示例。

TextView textView;
SpannableStringBuilder ssb;
final ForegroundColorSpan BLUE = new ForegroundColorSpan(Color.BLUE);
final ForegroundColorSpan RED = new ForegroundColorSpan(Color.RED);

// 1: baseline
// all RED
textView = findViewById(R.id.text1);
ssb = new SpannableStringBuilder("Hello world!");
ssb.setSpan(BLUE, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(RED, 0, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ssb);

// 2: reverse the setSpan() call order; not always convenient
// BLUE and RED
textView = findViewById(R.id.text2);
ssb = new SpannableStringBuilder("Hello world!");
ssb.setSpan(RED, 0, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(BLUE, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ssb);

// 3: give BLUE higher priority; BLUE applies first and RED overrides it
// all RED
textView = findViewById(R.id.text3);
ssb = new SpannableStringBuilder("Hello world!");
ssb.setSpan(BLUE, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (0x01 << Spanned.SPAN_PRIORITY_SHIFT));
ssb.setSpan(RED, 0, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (0x00 << Spanned.SPAN_PRIORITY_SHIFT));
textView.setText(ssb);

// 4: give RED higher priority; RED applies first and BLUE overrides it
// BLUE and RED
textView = findViewById(R.id.text4);
ssb = new SpannableStringBuilder("Hello world!");
ssb.setSpan(BLUE, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (0x00 << Spanned.SPAN_PRIORITY_SHIFT));
ssb.setSpan(RED, 0, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | (0x01 << Spanned.SPAN_PRIORITY_SHIFT));
textView.setText(ssb);

Span priority demo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接