Eugene
Eugene

Reputation: 1011

How to merge some spannable objects?

I divide a spannable object into 3 parts, do different operations, and then I need to merge them.

Spannable str = editText.getText();
Spannable selectionSpannable = new SpannableStringBuilder(str, selectionStart, selectionEnd);
Spannable endOfModifiedSpannable = new SpannableStringBuilder(str, selectionEnd, editText.getText().length());
Spannable beginningOfModifiedSpannable = new SpannableStringBuilder(str, 0, selectionStart);            

How can I do it? I haven't found the required method or constructor to do it.

Upvotes: 77

Views: 32624

Answers (5)

Mardann
Mardann

Reputation: 2163

Use SpannableStringBuilder.

Even better- make a kotlin operator overload:

operator fun Spannable.plus(other: Spannable): Spannable{
    return SpannableStringBuilder(this).append(other)
}

just throw that in any kotlin file as a top level function.

and the you can concatenate using +:

val spanA = ...
val spanB = ...

val concatenatedSpan = spanA + spanB

Upvotes: 8

AlexKost
AlexKost

Reputation: 2972

I know this is old. But after modifying kotlin stdlib a bit I've got this code:

fun <T> Iterable<T>.joinToSpannedString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): SpannedString {
    return joinTo(SpannableStringBuilder(), separator, prefix, postfix, limit, truncated, transform)
            .let { SpannedString(it) }
}

Hope it might help somebody.

Upvotes: 9

nulldev
nulldev

Reputation: 615

As marwinXXII said in a comment, using TextUtils.concat does work but can cause loss of styles in some cases when you have multiple instances of the same span in a single CharSequence.

A workaround could be to write the CharSequence to a Parcel and then read it back. Example Kotlin extension code to do this below:

fun CharSequence.cloneWithSpans(): CharSequence {
    val parcel = Parcel.obtain()
    TextUtils.writeToParcel(this, parcel, 0)
    parcel.setDataPosition(0)
    val out = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel)
    parcel.recycle()
    return out
}

Example usage of this code:

TextUtils.concat(*yourListOfText.map { it.cloneWithSpans() }.toTypedArray())

Now you can concatenate tons of CharSequences without worrying about losing any of the styles and formatting you have on them!

Note that this will work for most styles, it doesn't work all the time but should be enough to cover all the basic styles.

Upvotes: 2

Eugene
Eugene

Reputation: 1011

Thanks, it works. I have noticed that I can merge even 3 spannable object:

(Spanned) TextUtils.concat(foo, bar, baz)

Upvotes: 23

xil3
xil3

Reputation: 16449

You could use this:

TextUtils.concat(span1, span2);

http://developer.android.com/reference/android/text/TextUtils.html#concat(java.lang.CharSequence...)

Upvotes: 184

Related Questions