解释Span标志的含义,如SPAN_EXCLUSIVE_EXCLUSIVE

时间:2012-03-26 20:23:48

标签: android

有人可以用示例清楚地解释每个span flags SPAN_EXCLUSIVE_EXCLUSIVESPAN_MARK_MARK的含义以及何时使用哪些标记?

当它说:

时,我不明白官方文件
  

SPAN_EXCLUSIVE_EXCLUSIVE类型的范围不会展开以包含文字   插入到起点或终点。

“扩展到包含”是指插入跨度后进行的编辑吗?

这是否意味着这些标志不会影响具有不可变文本的Spannables?

3 个答案:

答案 0 :(得分:108)

标志不代表什么

当我第一次看到var output = Babel.transform(code, { sourceType: 'script' }); 标志的INCLUSIVEEXCLUSIVE部分时,我认为他们只是告诉跨度是否包含跨度的起始和结束索引位置。这不是真的。让我用下面的例子来说明这一点。

Spannable

结果如下:

String myString = "01234"; int start = 1; int end = 3; int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing SpannableString spannableString = new SpannableString(myString); ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED); spannableString.setSpan(foregroundSpan, start, end, spanFlag); textView.setText(spannableString);

enter image description here

SPAN_INCLUSIVE_INCLUSIVE

enter image description here

SPAN_INCLUSIVE_EXCLUSIVE

enter image description here

SPAN_EXCLUSIVE_INCLUSIVE

enter image description here

他们都是一样的!标志不会影响范围。 范围始终包括其起始索引处的字符,并排除结束索引处的字符。

旗帜的真正含义

Spannable标志的SPAN_EXCLUSIVE_EXCLUSIVEINCLUSIVE部分实际告诉跨度是否应包含在开始或结束位置插入的文字< / em>的

这是一个用于说明这一点的修改示例。

EXCLUSIVE

以下是在末尾插入String myString = "01234"; int start = 1; int end = 3; int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing // set the span SpannableStringBuilder spannableString = new SpannableStringBuilder(myString); ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED); spannableString.setSpan(foregroundSpan, start, end, spanFlag); // insert the text after the span has already been set // (inserting at start index second so that end index doesn't get messed up) spannableString.insert(end, "x"); spannableString.insert(start, "x"); textView.setText(spannableString); 并开始索引后的结果:

x

enter image description here

SPAN_INCLUSIVE_INCLUSIVE

enter image description here

SPAN_INCLUSIVE_EXCLUSIVE

enter image description here

SPAN_EXCLUSIVE_INCLUSIVE

enter image description here

注释

  • 这个答案大部分描述了OP已经知道的事情。我只是将它添加到像我这样不了解这些东西的未来访客中。
  • 在第二个示例中,我必须使用SPAN_EXCLUSIVE_EXCLUSIVE,因为SpannableStringBuilder中的文本是不可变的,因此您无法在其中插入文本。因此,对于SpannableString,标志通常是无意义的。但是,可以想象一种情况,即SpannableString的范围被复制到SpannableStringSpannableStringBuilder,并且从那里标志就有意义。
  • See this answer了解EditableSpannableStringSpannableStringBuilder等之间的差异。

答案 1 :(得分:91)

  

“扩展到包含”是指插入跨度后进行的编辑吗?

是。例如,假设我们有以下内容:

快狐跳了起来。

如果我们在粗体跨度上使用SPAN_EXCLUSIVE_EXCLUSIVE,并且我们在跨度的中间插入文本,它仍然是粗体:

快速棕色狐狸跳了起来。

但是,如果我们在粗体跨度的开头或末尾插入文本,则插入的文本不是粗体:

真正的快狐跳了起来。

但是,如果我们使用了SPAN_INCLUSIVE_EXCLUSIVE,那么在开头插入文本将作为范围的一部分包含在内,我们将拥有:

非常快的狐狸跳了起来。

  

这是否意味着这些标志不会影响具有不可变文本的Spannables?

我会说他们对不可变文本的使用有限。大多数情况下,这些内容将与SpannableStringBuilder一起使用,或者使用其中的内容(例如EditText)。

答案 2 :(得分:1)

我们作为资源保存在res / values目录中的xml文件中的字符串值可以使用android.text.Spannable接口中定义的方法设置样式,android.text.Spanned接口中定义的字段(Spannable)是Spanned的子接口),android.text.SpannableStringBuilder类(SpannableStringBuilder是Spannable的子类),并且在android.text.style包中定义了类,特别是android.text.style.ForegroundColorSpan和android.text。 style.StyleSpan类。 由于SpannableStringBuilder是Spannable的子类,因此Spannable是Spanned的子接口。所有Spannable接口的字段和Spannable接口的方法的完整实现都存在于SpannableStringBuilder类中。

1.如果要设置文本资源的样式,我们首先必须使用Resources对象中的方法getString(int resource_id)方法获取资源ID,以获取与Context子类关联的Resources对象,我们称之为getResources()方法。例如 -

String title = getResources()。getString(R.string.string_title);

2.现在我们需要使用public no参数构造函数或任何其他公共构造函数创建一个SpannableStringBuilder对象。

3.SpannableStringBuilder以一种复杂的方式工作。我们可以使用其中一种追加方法将文本追加到SpannableStringBuilder.SpannableStringBuilder所持有的文本的某些部分可以标记为跨越,只有该部分被设置样式(带颜色,字体等),当在任何索引处的SpannableStringBuilder对象中附加新文本时,如果新文本也将被标记为已修改,则由Spanned接口的字段定义。 我们调用由Spannable接口声明并由SpannableStringBuilder类实现的setSpan(Object what,int start,int end,int flags)方法。 这里是android.text.style.StyleSpan包类的对象,这个对象定义了我们想要应用的样式的类型,flags是Spanned接口中定义的字段之一,这个flags参数指定何时a如果新文本也将被标记为跨越,则新文本将附加在此SpannableStringBuilder对象的任何索引中。

4. android.text.style.StyleSpan包的不同类定义了不同的样式,但截至目前我只知道android.text.style.StyleSpan类的一种用法和android.text的一种用法。 style.ForegroundColorSpan类。 StyleSpan类的一个公共构造函数接受一个int值,该值可能是android.graphics.Typeface类(BOLD,BOLD_ITALIC,ITALIC,NORMAL)中定义的字段之一的值。由于这些字段名称建议他们将样式化文本粗体或粗体或斜体或正常。 例如 -

StyleSpan style_span = new StyleSpan(Typeface.ITALIC);

ForegroundColorSpan类的一个公共构造函数接受一个int值,该值可以是任何十六进制的argb颜色值,也可以是android.graphics.Color类中定义的字段之一的值(BLACK,BLUE,CYAN,DKGRAY,灰色,绿色,LTGRAY,MAGENTA,红色,透明,白色,黄色。由于这些字段的名称建议他们为文本着色。为了给构造函数提供一个argb十六进制颜色值作为int,我们用0X开始十六进制值或者0x,java然后自动将十六进制值转换为其int等效值。 例如 -

ForegroundColorSpan fore_ground_color_Span = new ForegroundColorSpan(Color.RED);

5.在setSpan(Object what,int start,int end,int flags)方法中, start和end定义要标记为spanned的文本的初始范围,start指定起始字符的索引,end指定通过结束字符的字符的索引,例如 - 对于一个字符串&#34; 01234&#34;

new SpannableStringBuilder(&#34; 01234&#34;)。setSpan(foreground_color_span,1,3,span_flag);

最初只会将12标记为跨区,因此起始字符为&#39; 1&#39;由起始索引指定,结束字符是索引(end-1)指定的2。 因此,如果我们为开始和结束赋予相同的值,那么最初将没有文本覆盖,范围将为零,对于上面的示例,如果start和end都是1,则起始字符为1但结束字符为0.这没有任何意义,在这种情况下,最初将没有标记为跨越的文本。

6.现在,Spanned接口的某些字段的工作方式如下所述。 附加新文本时.......... SPAN_EXCLUSIVE_EXCLUSIVE不会在起始字符之前和结束字符之后将任何文本标记为已跨越,但会在起始字符之后或结束字符之前标记任何文本为跨越,SPAN_EXCLUSIVE_EXCLUSIVE是SPAN_POINT_MARK的同义词,如果范围为零,则表示最初没有文本被标记为跨越,那么任何索引附加的任何文本都不会被标记为跨越此标志,

SPAN_EXCLUSIVE_INCLUSIVE不会将起始字符之前附加的任何文本标记为spanned,而是根据我的测试标记在起始字符之后附加的任何文本或在结束字符之前或之后附加的任何文本,根据我的测试SPAN_EXCLUSIVE_INCLUSIVE是SPAN_POINT_POINT的同义词,如果范围为零,这意味着最初没有文本被标记为跨越,那么任何索引处附加的任何文本都不会被标记为跨越此标志,

SPAN_INCLUSIVE_EXCLUSIVE不会将结尾字符之前附加的任何文字标记为已跨越,但会根据我的测试标记在起始字符之后或之前附加的任何文本或在结束字符之后附加的任何文本,根据我的测试SPAN_INCLUSIVE_EXCLUSIVE是SPAN_MARK_MARK的同义词,如果范围为零,这意味着最初没有文本被标记为跨越,那么任何索引处附加的任何文本都不会被标记为跨越此标志,

SPAN_INCLUSIVE_INCLUSIVE标记在开始和结束字符之后或之前附加的任何文本,SPAN_INCLUSIVE_INCLUSIVE是SPAN_MARK_POINT的同义词,如果范围为零,则表示最初没有文本标记为跨越,然后在任何索引处附加任何文本在开始或结束字符之后或之前始终标记为跨越此标志,

我无法正确理解Spanned接口中定义的其他标志常量。

7.现在我们可以使用其中一个append方法或其中一个insert方法在我们的SpannableStringBuilder对象中附加任何文本 -

SpannableStringBuilder text = new SpannableStringBuilder(); ...... text.append(STRING_VALUE); // append(CharSequence text)将给定的String附加到结尾 // insert(int where,CharSequence tb)在索引为(where-1)的字符后插入给定的String

插入此SpannableStringBuilder的新文本将标记为&#34; spanned and styled&#34;是否依赖于我们为之前调用setSpan(Object what,int start,int end,int flags)方法指定的标志。

8.如果我们想在SpannableStringBuilder对象中对文本应用多个样式,那么我们可以再次调用setSpan(Object what,int start,int end,int flags)方法并指定样式到什么参数,以及最初要设置样式的开始和结束,然后使用flag参数指定样式在插入任何新文本时的行为方式。 这里重要一点是,当我们调用span方法时,我们指定的样式与start,end和flag配对,这与以前对span方法的任何调用无关,这意味着每次调用span方法都应用一个样式,独立于任何其他样式也可以应用于同一文本。即使我们再次应用相同的样式但是将新对象应用于&#34;什么&#34;参数,这种样式也独立于先前应用的相同样式工作,只有修改已经应用的样式的方法是指定相同的对象到&#34;什么&#34;参数。 例如 -

    TextView txv=(TextView)findViewById(R.id.textView9);
    String myString = "01234";
    Object ob;
    int start = 1;
    int end = 4;
    int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; 
    SpannableStringBuilder spannableString = new SpannableStringBuilder(myString);
    ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
    ob=foregroundSpan;
    spannableString.setSpan(foregroundSpan, start, end, spanFlag);
    txv.setText(spannableString);

这将导致txv有&#34; 01234&#34 ;,其中部分&#34; 123&#34;是红色的。

    end=3;
    spanFlag = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
    spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, spanFlag);
    txv.setText(spannableString);

这将导致txv有&#34; 01234&#34 ;,其中部分&#34; 123&#34;是红色的,子部分是&#34; 12&#34;是粗体(脂肪)和红色但是&#34; 3&#34;由于&#34;结束&#34;只是红色不大胆值。

    spannableString.insert(end, "x");
    spannableString.insert(start, "x");
    txv.setText(spannableString);

这将使txv具有&#34; 0x12x34&#34;,其中部分&#34; x12x3&#34;是红色的,只有&#34; 12x3&#34;大胆, 发生这种情况是因为红色造型最初应用于文本&#34; 123&#34;使用标志SPAN_INCLUSIVE_INCLUSIVE,这意味着在1和3之后或之前附加的任何文本总是包含在红色样式区域中,因此&#34; x12x3&#34;是红色的 大胆的造型最初应用于文本&#34; 12&#34;使用标志SPAN_EXCLUSIVE_INCLUSIVE,这意味着在1之前附加的任何文本都不包含在样式区域中,但是在1之后和之后或之前附加的任何文本总是包含在粗体样式区域中,因此只有&#34; 12x3&#34;大胆。

    int end=3;
    spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; 
    foregroundSpan = new ForegroundColorSpan(Color.RED);
    spannableString.setSpan(foregroundSpan, start, end, spanFlag);
    txv.setText(spannableString);

这将在文本&#34; x1&#34;上引起另一个独立的红色样式,但由于已经将其他红色样式应用于文本&#34; x12x3&#34;,我们将看到txv没有区别。 要实际更改以前应用的红色样式,我们需要传递与第一次调用setSpan方法时相同的ForegroundColorSpan对象,我们应该使用以下代码而不是上面的代码,

    int end=3;
    spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; 
    spannableString.setSpan(ob, start, end, spanFlag); //ob refers to the same the styling object as we specified on the first occasion
    txv.setText(spannableString);

这只会导致&#34; x1&#34;变成红色,如果我们在&#34; 1&#34;之后附加任何文字或者在&#34; x&#34;之前,那个文本将不会包含在红色样式区域中,而是包含在&#34; x&#34;之后的任何文本。之前&#34; 1&#34;因为我们这次指定了标志SPAN_EXCLUSIVE_EXCLUSIVE,所以它总是包含在红色样式区域中。

9.最后,如果我们要完全删除样式及其span标志规则,那么我们可以调用SpannableStringBuilder类实现的Spannable接口定义的removeSpan(Object what)方法,我们需要传递相同的样式对象我们给setSpan方法的removeSpan方法。

由于上述答案,特别是颜色示例帮助我很好地理解了这些标志。