Android - Applying a new StyleSpan removes previously applied Spans

347 views Asked by At

I am making an app that requires the Text Formatting Features such as making the selected text Bold, Italic, Strike through, Underline, etc. I have used the StyleSpan(Typeface.BOLD), StyleSpan(Typeface.Italic), UnderlineSpan(), StrikethroughSpan() provided by android. All these are working fine. But, when I try to apply a new span over a previous span, the previously applied span is removed and the new one is applied. Here is the function that I am using to apply the format based upon the button click :

  fun formatText(typefaceCode: StyleSpan = StyleSpan(Typeface.BOLD), isUnderline : Boolean = false, isStrikeThrough : Boolean = false, isQuote : Boolean = false){
            val selectionStart: Int = mEditTextNoteContent.selectionStart
            val selectionEnd: Int = mEditTextNoteContent.selectionEnd
            val selectedText: String = mEditTextNoteContent.text.toString().substring(selectionStart, selectionEnd)
            val formattedString = SpannableStringBuilder(selectedText)
            when {
                isUnderline -> formattedString.setSpan(UnderlineSpan(), 0, selectedText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                isStrikeThrough -> formattedString.setSpan(StrikethroughSpan(), 0, selectedText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                isQuote -> mEditTextNoteContent.text.replace(selectionStart, selectionEnd,  "\"" + selectedText + "\"")
                else -> formattedString.setSpan(typefaceCode, 0, selectedText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            if(!isQuote)
                mEditTextNoteContent.text.replace(selectionStart, selectionEnd, formattedString)
 }

Initially, I had the following formattingFormatting With Bold and Strike Through Then, I selected the entire text and applied Bold. It should have shown everything bold along with the Strike Through from the previous formatting, but it does not happen. Here is what is happening : Text gets Bold, but Strike Through gets removed.

2

There are 2 answers

0
Harikrishnan VK On

The problem was using the replace() on EditText. Instead of using the replace(), you must use the editText.setSpan() method.

Therefore, the updated Code looks like :

fun formatText(typefaceCode: StyleSpan = StyleSpan(Typeface.BOLD), isUnderline : Boolean = false, isStrikeThrough : Boolean = false, isQuote : Boolean = false, isBulletSpan : Boolean = false){
    val selectionStart: Int = mEditTextNoteContent.selectionStart
    val selectionEnd: Int = mEditTextNoteContent.selectionEnd
    val selectedText: CharSequence = TextUtils.substring(mEditTextNoteContent.text, selectionStart, selectionEnd)
    when{
        isUnderline -> mEditTextNoteContent.text.setSpan(UnderlineSpan(), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        isStrikeThrough -> mEditTextNoteContent.text.setSpan(StrikethroughSpan(), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        isQuote -> mEditTextNoteContent.text.replace(selectionStart, selectionEnd,  "\"" + selectedText + "\"")
        else -> mEditTextNoteContent.text.setSpan(typefaceCode, selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    }
}

This will not overwrite the previously used Spans

4
CommonsWare On
        val selectedText: String = mEditTextNoteContent.text.toString().substring(selectionStart, selectionEnd)

toString() wipes out spans, as you are specifically asking it to switch to String from CharSequence.

Use TextUtils.substring() to work directly with the CharSequence. It probably results in something like:

        val selectedText: CharSequence = TextUtils.substring(mEditTextNoteContent.text, selectionStart, selectionEnd)