1

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 Answers2

1

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

0
        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)
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • @HarikrishnanVK: I noticed a typo in my answer. I had just `mEditTextNoteContent` instead of `mEditTextNoteContent.text` for the `TextUtils.substring()` call. Otherwise, I cannot really help you without more details about what "not working" means. – CommonsWare Apr 10 '20 at 17:31
  • Yes, I had noticed the typo before. So I did use mEditTextNoteContent.text in the above code. But it is not solving the problem. – Harikrishnan VK Apr 10 '20 at 17:36
  • @HarikrishnanVK: Make sure that you are not converting to `String` anywhere else -- keep it all as `Spannable` types (or `CharSequence`) for the initial retrieval from the `EditText`. You can call `getSpans()` on your `Spannable` at various points to see where you lose the spans. – CommonsWare Apr 10 '20 at 18:14
  • I have checked it everywhere. I am not converting the EditText to String anywhere. Do you think it might be happening because I am using replace method ? – Harikrishnan VK Apr 11 '20 at 09:21