有人可以清楚地举例解释每个的跨度标志像SPAN_EXCLUSIVE_EXCLUSIVE和SPAN_MARK_MARK意思,什么时候用什么标志?
当它说:我不明白官方文件:
类型的跨度
SPAN_EXCLUSIVE_EXCLUSIVE不会扩展为包括在其起点或终点插入的文本.
"扩展到包含"是指插入跨度后进行的编辑吗?
这是否意味着这些标志不会影响具有不可变文本的Spannables?
Sur*_*gch 125
当我第一次看到INCLUSIVE和EXCLUSIVE在部分地区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);
Run Code Online (Sandbox Code Playgroud)
结果如下:
SPAN_INCLUSIVE_INCLUSIVE
SPAN_INCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_INCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
他们都是一样的!标志不会影响范围.跨度始终包括其起始索引处的字符,并排除结束索引处的字符.
Spannable标志的INCLUSIVE和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);
Run Code Online (Sandbox Code Playgroud)
以下是插入x结尾并开始索引后的结果:
SPAN_INCLUSIVE_INCLUSIVE
SPAN_INCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_INCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
SpannableStringBuilder因为a中的文本SpannableString是不可变的,所以你不能在其中插入文本.因此,标志对于a来说通常是没有意义的SpannableString.然而,人们可以想象这样一种情况,即从一个SpannableString被转移到一个SpannableStringBuilder或那里的跨度Editable,并且那里的标志将具有意义.SpannableString,SpannableStringBuilder,Editable,等等.Com*_*are 92
"扩展到包含"是指插入跨度后进行的编辑吗?
是.例如,假设我们有以下内容:
该快速狐狸跳了.
如果我们使用SPAN_EXCLUSIVE_EXCLUSIVE粗体跨度,并且我们在跨度的中间插入文本,它仍然是粗体:
在敏捷的棕色狐狸跳了下去.
但是,如果我们在粗体跨度的开头或末尾插入文本,则插入的文本不是粗体:
真快的狐狸跳了起来.
但是,如果我们使用过SPAN_INCLUSIVE_EXCLUSIVE,那么在开头插入文本将作为跨度的一部分包含在内,我们将:
在非常快的狐狸跳了下去.
这是否意味着这些标志不会影响具有不可变文本的Spannables?
我会说他们对不可变文本的使用有限.大多数情况下,这些将与SpannableStringBuilder在封面下使用它们的东西一起使用(例如,EditText).
小智 5
我们作为资源保存在 res/values 目录中的 xml 文件中的 String 值可以使用 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.现在要设置文本资源的样式,我们必须首先使用资源对象的方法 getString(int resource_id) 获取其资源 id,以获取与 Context 子类关联的资源对象,我们调用 getResources() 方法。对于例子-
String title = getResources().getString(R.string.string_title);
2.现在我们需要创建一个 SpannableStringBuilder 对象及其公共无参数构造函数或任何其他公共构造函数。
3.SpannableStringBuilder 的工作方式有点复杂。我们可以使用 append 方法之一将文本附加到 SpannableStringBuilder。SpannableStringBuilder 保存的文本的某些部分可以标记为跨区,并且只有该部分被设置样式(带有颜色、字体等)。 ),当一个新文本被附加到一个 SpannableStringBuilder 对象中的任何索引处时,如果新文本也会被标记为 spaned 或 not,这是由 Spanned 接口的字段定义的。我们调用由 Spannable 接口声明并由 SpannableStringBuilder 类实现的 setSpan(Object what, int start, int end, int flags) 方法。这里what是android.text.style.StyleSpan包的一个类的对象,这个对象定义了我们要应用的样式的类型,flags是Spanned接口中定义的字段之一,
4.android.text.style.StyleSpan包的不同类定义了不同的样式,但目前我只知道android.text.style.StyleSpan类的一种用法和android.text.style.ForegroundColorSpan类的一种用法班级。StyleSpan 类的一个公共构造函数采用一个 int 值,该值可能是 android.graphics.Typeface 类( BOLD,BOLD_ITALIC,ITALIC,NORMAL )中定义的字段之一的值。因为这些字段名称表明它们将设置文本样式作为粗体或bold_italic 或斜体或正常。例如-
StyleSpan style_span=new StyleSpan(Typeface.ITALIC);
ForegroundColorSpan 类的一个公共构造函数采用一个 int 值,该值可以是任何十六进制 argb 颜色值,也可以是 android.graphics.Color 类中定义的字段之一的值 (BLACK,BLUE,CYAN,DKGRAY,GRAY,GREEN ,LTGRAY,MAGENTA,RED,TRANSPARENT,WHITE,YELLOW )。因为这些字段的名称表明它们为文本着色。要将 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指定了通过结束字符的字符的索引,例如 - 对于字符串“01234”
new SpannableStringBuilder("01234").setSpan(foreground_color_span, 1, 3, span_flag);
将导致最初仅将 12 标记为跨区,因此起始字符是由开始索引指定的“1”,而结束字符是由索引 (end-1) 指定的 2。因此,如果我们为 start 和 end 提供相同的值,那么最初将没有文本覆盖并且范围将为零,对于上面的示例,如果 start 和 end 均为 1,则起始字符为 1 但结束字符为0.这在这种情况下没有意义,最初不会有文本标记为跨度。
6.现在 Spanned 接口的一些字段如下所述工作。附加新文本时.......... SPAN_EXCLUSIVE_EXCLUSIVE 不会将任何附加在起始字符之前和结束字符之后的文本标记为跨区,而是将任何附加在起始字符之后或结束字符之前的文本标记为作为跨区,SPAN_EXCLUSIVE_EXCLUSIVE 是 SPAN_POINT_MARK 的同义词,如果范围为零意味着最初没有文本被标记为跨区,则附加在任何索引处的任何文本都不会被标记为跨区,
SPAN_EXCLUSIVE_INCLUSIVE 不会将在起始字符之前附加的任何文本标记为跨区,而是将在起始字符之后附加的任何文本或在结束字符之前或之后附加的任何文本标记为跨区,根据我的测试,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.现在我们可以在我们的 SpannableStringBuilder 对象中附加任何文本,例如使用 append 方法之一或插入方法之一 -
SpannableStringBuilder text = new SpannableStringBuilder(); ...... text.append(string_value); //append(CharSequence text) 将给定的字符串追加到末尾 //insert(int where, CharSequence tb) 在索引为 (where-1) 的字符之后插入给定的字符串
插入到这个 SpannableStringBuilder 的新文本将被标记为“spanned and styled”与否,这取决于我们为之前调用 setSpan(Object what, int start, int end, int flags) 方法指定的标志。
8.如果我们想对一个 SpannableStringBuilder 对象中的文本应用多个样式,那么我们可以再次调用 setSpan(Object what, int start, int end, int flags) 方法并将样式指定给 what 参数,然后初始样式的开始和结束,然后是标志参数,用于指定插入任何新文本时样式的行为方式。这里重要的一点是,当我们调用 span 方法时,我们指定的样式与 start、end 和 flag 配对,这与之前对 span 方法的任何调用无关,这意味着对 span 方法的每次调用都会应用一个样式独立于任何其他样式工作,这些样式也应用于相同的文本。即使我们再次应用相同的样式但将新对象应用于“what”参数,此样式也独立于先前应用的相同样式,唯一修改已应用样式的方法是为“what”参数指定相同的对象。例如-
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);
Run Code Online (Sandbox Code Playgroud)
这将导致 txv 有“01234”,其中“123”部分是红色的。
end=3;
spanFlag = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, spanFlag);
txv.setText(spannableString);
Run Code Online (Sandbox Code Playgroud)
这将导致 txv 有“01234”,其中“123”部分是红色,子部分“12”既是粗体(胖)又是红色,但“3”只是红色而不是粗体,因为“结束”价值。
spannableString.insert(end, "x");
spannableString.insert(start, "x");
txv.setText(spannableString);
Run Code Online (Sandbox Code Playgroud)
这将导致 txv 具有“0x12x34”,其中“x12x3”部分为红色,只有“12x3”为粗体,这是因为红色样式最初应用于带有标志 SPAN_INCLUSIVE_INCLUSIVE 的文本“123”,这意味着任何文本附加在 1 和 3 之后或之前总是包含在红色样式区域中,因此“x12x3”是红色粗体样式最初应用于带有标志 SPAN_EXCLUSIVE_INCLUSIVE 的文本“12”,这意味着附加在 1 之前的任何文本不包括在样式区域但在 1 之后和 2 之后或之前附加的任何文本始终包含在粗体样式区域中,因此只有“12x3”是粗体。
int end=3;
spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, start, end, spanFlag);
txv.setText(spannableString);
Run Code Online (Sandbox Code Playgroud)
这将在文本“x1”上产生另一个独立的红色样式,但由于已经将另一个红色样式应用于文本“x12x3”,因此我们将看不到 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);
Run Code Online (Sandbox Code Playgroud)
这将仅导致“x1”为红色,并且如果我们在“1”之后或“x”之前附加任何文本,那么该文本将不会包含在红色样式区域中,而是“x”之后和“之前的任何文本” 1" 始终包含在红色样式区域中,因为我们这次指定了标志 SPAN_EXCLUSIVE_EXCLUSIVE。
9.最后,如果我们想彻底删除一个样式及其span标志规则,那么我们可以调用由SpannableStringBuilder类实现的Spannable接口定义的removeSpan(Object what)方法,我们需要将相同的样式对象传递给removeSpan方法正如我们对 setSpan 方法所做的那样。
感谢上述答案,特别是颜色示例帮助我正确理解这些标志。
| 归档时间: |
|
| 查看次数: |
21523 次 |
| 最近记录: |