Как перебрать пролеты в SpannedString или SpannableString в Android

Если у меня есть 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);

Как бы я прошел через пролеты в результате String?

1 ответ

Решение

Перебирая пролеты в порядке

Ты можешь использовать getSpans чтобы получить массив пролетов в Spanned или же SpannableString, Тем не менее, просто цикл через 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);
}

Выход:

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

Спасибо этому коду за идеи.

Типы пролетов

Обычно при прохождении через пролеты вы выбираете определенный тип пролета. Например, если вы хотите удалить все диапазоны цветов переднего плана, вы можете сделать следующее:

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

// loop through spans
for (ForegroundColorSpan span : spans) {
    spannableString.removeSpan(span);
}

Обратите внимание, что это не будет работать с SpannedString потому что пролеты в SpannedString не являются изменяемыми (см. этот ответ).

Если вы хотите получить все пролеты любого типа, вы должны установить тип как Object.class,

Object[] spans = spannableString.getSpans(0, spannableString.length(), Object.class);

Если вы хотите, чтобы все промежутки, которые влияют на внешний вид на уровне персонажа, вы бы использовали CharacterStyle.class, Если в цикле вы хотите дополнительно ограничить промежутки для тех, кто принадлежит MetricAffectingSpanВы могли бы сделать это так.

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

Вот общая иерархическая разбивка типов промежутков. Это может быть не полным. Прочитайте 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
Другие вопросы по тегам