如何在Android中的SpannedString或SpannableString中遍历跨度

Sur*_*gch 8 android loops spanned spannablestring

如果我有一个SpannedString(或SpannableString)这样的

在此输入图像描述

SpannableString spannableString = new SpannableString("Hello World!");
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
BackgroundColorSpan backgroundSpan = new BackgroundColorSpan(Color.YELLOW);
spannableString.setSpan(foregroundSpan, 1, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(backgroundSpan, 3, spannableString.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
Run Code Online (Sandbox Code Playgroud)

我将如何在结果的范围内循环String

Sur*_*gch 21

按顺序循环

您可以使用getSpans以获取一个Spanned或多个跨度的数组Spannable String.但是,只是循环getSpans结果不一定会按顺序给你.为了得到它们你可以使用nextSpanTransition.

这是一个与SpannedString问题中的示例类似的示例.(A SpannableString会起作用.)绿线表示跨度过渡的位置.默认情况下,文本为黑色.

spannable字符串示例

代码找到下一个跨度转换,然后获取当前范围内的所有跨度.

int next;
for (int i = 0; i < spannableString.length(); i = next) {

    // find the next span transition
    next = spannableString.nextSpanTransition(i, spannedString.length(), CharacterStyle.class);

    // get all spans in this range
    int numOfSpans = 0;
    CharacterStyle[] spans = spannableString.getSpans(i, next, CharacterStyle.class);
    for(int j = 0; j < spans.length; j++) {
        numOfSpans++;
    }

    Log.i("TAG", "spans from " + i + " to " + next + ": " + numOfSpans);
}
Run Code Online (Sandbox Code Playgroud)

输出:

spans from 0 to 1: 0
spans from 1 to 3: 1
spans from 3 to 8: 2
spans from 8 to 11: 1
spans from 11 to 12: 0
Run Code Online (Sandbox Code Playgroud)

感谢这个代码的想法.

跨度的类型

通常在循环跨越时,您可以选择某种类型的跨度.例如,如果要删除所有前景颜色跨度,可以执行以下操作:

// get spans
ForegroundColorSpan[] spans = spannableString.getSpans(0, spannableString.length(), ForegroundColorSpan.class);

// loop through spans
for (ForegroundColorSpan span : spans) {
    spannableString.removeSpan(span);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这不适用于a,SpannedString因为a SpannedString中的跨距不可变(请参阅此答案).

如果您想获得任何类型的所有跨度,您可以将类型设置为Object.class.

Object[] spans = spannableString.getSpans(0, spannableString.length(), Object.class);
Run Code Online (Sandbox Code Playgroud)

如果您想要在角色级别上影响外观的所有跨度,您可以使用CharacterStyle.class.如果你想在循环内进一步限制那些属于的范围MetricAffectingSpan,你可以这样做.

CharacterStyle[] spans = spannableString.getSpans(0, spannableString.length(), CharacterStyle.class);
for (CharacterStyle span : spans) {
    if (span instanceof MetricAffectingSpan) {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是范围类型的一般分层细分.它可能不完整.阅读Spans,一个强大的概念以获取更多信息.

Object
    CharacterStyle
        BackgroundColorSpan
        ClickableSpan
            URLSpan
        ForegroundColorSpan
        MaskFilterSpan
        StrikethroughSpan
        SuggestionSpan
        UnderlineSpan 
        MetricAffectingSpan
            AbsoluteSizeSpan
            LocaleSpan
            RelativeSizeSpan
            ReplacementSpan
                DynamicDrawableSpan
                    ImageSpan 
            ScaleXSpan
            StyleSpan
            SubscriptSpan
            SuperscriptSpan
            TextAppearanceSpan
            TypefaceSpan 
    ParagraphStyle
        AlignmentSpan
            AlignmentSpan.Standard
        BulletSpan
        DrawableMarginSpan
        IconMarginSpan
        LeadingMarginSpan
            LeadingMarginSpan.LeadingMarginSpan2
            LeadingMarginSpan.Standard
        LineBackgroundSpan
        LineHeightSpan
            LineHeightSpan.WithDensity
        QuoteSpan
        TabStopSpan
            TabStopSpan.Standard
        WrapTogetherSpan
Run Code Online (Sandbox Code Playgroud)