合并spannable对象时出错

时间:2011-01-12 13:31:26

标签: android

我想合并3个spannable对象。这段代码工作正常:

Spannable s1 = new SpannableStringBuilder("bold");
             s1.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, s1.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
             Spannable s2 = new SpannableStringBuilder("not");
             Spannable s3 = new SpannableStringBuilder("BOLD");
             s3.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, s3.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
             finishSpan = (Spanned) TextUtils.concat(s1,s2);
             finishSpan = (Spanned) TextUtils.concat(finishSpan,s3);

/////////////////////////////////////////////// ///////

finishSpan = (Spanned) TextUtils.concat(s1,s2,s3);

我有相同的代码但是当我合并3个对象时,结果是错误的。 我已经检查过某些元素的类型是否正确 beginningOfModifiedSpannable为粗体,selectionSpannable为normal,endOfModifiedSpannable为粗体 但他们的合并是错误的。只有结果字符串的最后一部分是粗体。为什么会这样?我上面有相同的代码,效果很好!

  Spannable str = contentText.getText();
            Spannable selectionSpannable = new SpannableStringBuilder(str, selectionStart, selectionEnd);
            StyleSpan[] ss = selectionSpannable.getSpans(0, selectionSpannable.length(), StyleSpan.class);

            boolean exists = false;
            for (int i = 0; i < ss.length; i++) {
                if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                 selectionSpannable.removeSpan(ss[i]);
                    exists = true;
                }
            }

            if (!exists){
                str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            else {

             Spannable endOfModifiedSpannable = new SpannableStringBuilder(str, selectionEnd, contentText.getText().length());
             Spannable beginningOfModifiedSpannable = new SpannableStringBuilder(str, 0, selectionStart);
             Spanned finishSpan = null;

             if(beginningOfModifiedSpannable.length() > 0) {

              if(endOfModifiedSpannable.length() > 0) {
               finishSpan = (Spanned) TextUtils.concat(beginningOfModifiedSpannable,selectionSpannable);
               finishSpan = (Spanned) TextUtils.concat(finishSpan,endOfModifiedSpannable);
                 }
              else {
               finishSpan = (Spanned) TextUtils.concat(beginningOfModifiedSpannable,selectionSpannable);
              }

             }
             else {
              if(endOfModifiedSpannable.length() > 0) {
               finishSpan = (Spanned) TextUtils.concat(selectionSpannable,endOfModifiedSpannable);
                     }
                  else {
                   finishSpan = selectionSpannable;
                  }
                 }
contentText.setText(finishSpan);

我再说一遍,我已经检查过3个部分是真的。例如。我有3个部分: Hel lo,wor ld

我注意到第一次合并是正确的:

finishSpan = (Spanned) TextUtils.concat(beginningOfModifiedSpannable,selectionSpannable);

看起来像 Hel lo,wor

但第二个错误

finishSpan = (Spanned) TextUtils.concat(finishSpan,endOfModifiedSpannable);

或合并错误:

finishSpan = (Spanned) TextUtils.concat(finishSpan,selectionSpannable,endOfModifiedSpannable);

错误字符串的结果是: 您好,WO的 RLD

但真正的结果必须是这样的:

赫尔 LO,世界

无意义!

2 个答案:

答案 0 :(得分:16)

问题是你很可能对两个部分使用相同的CharacterStyle实例,第1和第3部分。每次向Spannable对象添加样式时都需要使用新实例。

e.g。

    SpannableStringBuilder ssb = new SpannableStringBuilder("Hello,world");
    CharacterStyle c = new StyleSpan(Typeface.BOLD);
    ssb.setSpan(c, 0, 3, 0);
    ssb.setSpan(c, 9, 11, 0);

这将导致Hello,Wor ld

要获得正确的结果,您必须执行以下操作:

    SpannableStringBuilder ssb = new SpannableStringBuilder("Hello,world");
    CharacterStyle c = new StyleSpan(Typeface.BOLD);
    CharacterStyle c2 = new StyleSpan(Typeface.BOLD);
    ssb.setSpan(c, 0, 3, 0);
    ssb.setSpan(c2, 9, 11, 0);

答案 1 :(得分:0)

扩展@tagtraeumer的建议,这是另一个需要额外摆弄的情况。

显然,将相同的样式实例应用于不同的SpannableStringBuilder对象也不起作用。

例如。以下代码段仅将 mystyle 应用于 txt1 mystyle 都会从 txt2

中删除
TextView tv;
StyleSpan mystyle = new StyleSpan(Typeface.BOLD);

SpannableStringBuilder txt1 = new SpannableStringBuilder(somestring);
txt1.setSpan(mystyle,0,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

SpannableStringBuilder txt2 = new SpannableStringBuilder(anotherstring);
txt2.setSpan(mystyle,0,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

tv.setText(TextUtils.concat(txt1, txt2));

为了能够看到所有Spannable对象出现的样式,请创建唯一的样式对象,并将其应用于每个Spannable String Builder对象

TextView tv;
StyleSpan mystyle1 = new StyleSpan(Typeface.BOLD);
StyleSpan mystyle2 = new StyleSpan(Typeface.BOLD);

SpannableStringBuilder txt1 = new SpannableStringBuilder(somestring);
txt1.setSpan(mystyle1,0,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

SpannableStringBuilder txt2 = new SpannableStringBuilder(anotherstring);
txt2.setSpan(mystyle2,0,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

tv.setText(TextUtils.concat(txt1, txt2));