Clone SpannableStringBuilder

89
8

Я работаю над Activity, в котором я разбираю текст с символами разметки.
Что я делаю, это преобразование их в несколько типов ClickableSpans.


Проблема в том, что мне нужно реализовать функцию (позволяет вызывать ее функцию B), которая подразумевает перекрытие ClickableSpans и вызывает несколько проблем.


Итак, теперь я создаю новый SSB, обнаруживая перекрывающиеся промежутки и удаляя те, которые мне не нужны для этой конкретной функции. Хорошо работает.


НО, мне нужно иметь возможность вернуться к предыдущему SSB и, похоже, не работает.


ШАГ ПО ШАГУ:


// I CREATE THE SSBs
...
static SpannableStringBuilder ssb;
static SpannableStringBuilder ssbCopy;

// I IMPLEMENT MY CUSTOM FUNCTION THAT PARSES THE TEXT AND SETS THE SBB AS A TEXTVIEW CONTENT
...
textView.setMovementMethod(new LinkTouchMovementMethod());
ssb = addClickablePart(chapterTextStr, markupCharactersArray);
textView.setText(ssb);

// WHEN A BUTTON IS CLICKED I IMPLEMENT MY FUNCTION B. WHERE I CREATE A COPY OF MY ORIGINAL SSB AND STORE IT IN ssbCopy, AND SET IT AS THE TEXTVIEW CONTENT
...
ssbCopy = SpannableStringBuilder.valueOf(ssb);

// I REMOVE THE OVERLAPPING SPANS
...
overlapSpans = ssbCopy.getSpans(index, index+word.length(), TouchableSpan.class);

for (int c=0;c<overlapSpans.length;c++) {
ssbCopy.removeSpan(overlapSpans[c]);
}

// I SET THE NEW CLICKABLE SPANS
...
ssbCopy.setSpan(touchableSpan, index, index + word.length(), 0);

// AND SET THE NEW SSB CONTENT TO THE TEXTVIEW
textView.setText(ssbCopy);

// EVERYTHING WORKS FINE UP TO HERE
// BUT WHEN I TRY TO SET BACK THE ORIGINAL SSB BACK AS THE CONTENT OF MY TEXTVIEW WHEN THE USER CLICKS A BUTTON
...
textView.setText(ssb);

// THE ORIGINAL SSB IS EXACTLY LIKE THE COPY (ssbCopy) AND CONTAINS THE SAME CLICKABLE SPANS I ADDED. NOT ONLY THE ORIGINAL ONES


Я думаю, это может показаться несколько запутанным, и я не уверен, правильно ли я объяснил, но я не могу обойти это.


EDIT:


В соответствии с ответом kcoppock, я узнаю, что невозможно клонировать ssb, а valueOf (ssb) - это просто копия объекта.
Поэтому я закончил клонирование своего "ssb" вручную, перейдя все элементы и применив их к новому ssb. Вот так:


TouchableSpan[] spans = ssb.getSpans(0, ssb.length(), TouchableSpan.class);

ssbCopy = new SpannableStringBuilder(chapterTextStr+"dsadsa");

for (int c=0;c<spans.length;c++) {
TouchableSpan obj = spans[c];

ssbCopy.setSpan(obj, ssb.getSpanStart(obj), ssb.getSpanEnd(obj), 0);
}


Кстати, TouchableSpan - это настраиваемый класс, который я создал, который расширяет ClickableSpan

спросил(а) 2021-01-25T17:10:48+03:00 5 месяцев назад
1
Решение
77

Проблема здесь в использовании valueOf(). Он не делает то, что, по вашему мнению, делает. Все, что он делает, это вернуть объект, если он равен SpannableStringBuilder; в противном случае он переносит данный CharSequence в SpannableStringBuilder. Из источника:


public static SpannableStringBuilder valueOf(CharSequence source) {
if (source instanceof SpannableStringBuilder) {
return (SpannableStringBuilder) source;
} else {
return new SpannableStringBuilder(source);
}
}

Итак, по существу:

ssb == SpannableStringBuilder.valueOf(ssb);

Это один и тот же объект. SpannableStringBuilder не реализует Cloneable, поэтому нет простого способа сделать копию, кроме как просто создать две копии, например:


ssb = addClickablePart(chapterTextStr, markupCharactersArray);
ssbCopy = addClickablePart(chapterTextStr, markupCharactersArray);

ответил(а) 2021-01-25T17:10:48+03:00 5 месяцев назад
-4

Подпоследовательность метода в SpannableStringBuilder копирует промежутки. Вы можете сделать копию своего ssb, вызвав ssb.subsequence(0, ssb.length)


SpannableStringBuilder ssbCopy = (SpannableStringBuilder) ssb.subSequence(0, ssb.length());

https://developer.android.com/reference/android/text/SpannableStringBuilder.html#subSequence

ответил(а) 2021-01-25T17:10:48+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема