Как перебрать пролеты в 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
или же Spannable
String
, Тем не менее, просто цикл через getSpans
результаты не обязательно приведут их к вам в порядке. Чтобы получить их в порядке, вы можете использоватьnextSpanTransition
,
Вот пример с SpannedString
как пример в вопросе. (A SpannableString
будет работать так же.) Зеленые линии показывают, где переходы пролета. Текст черный по умолчанию.
Код находит следующий переход диапазона, а затем получает все диапазоны в текущем диапазоне.
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