Search code examples
javaandroidregexkotlinhighlight

Highlight text within square bracket (regex ?) Android kotlin


I would like to highlight all of the substring which are inside square brackets, ex: "[Toto] is [doing a lot of] stuff at the same time."
I know how to extract it.
I know how to highlight:

val str = SpannableString("Toto is doing a lot of stuff at the same time.")
str.setSpan(BackgroundColorSpan(Color.YELLOW), 0, 4, 0)
str.setSpan(BackgroundColorSpan(Color.YELLOW), 8, 22 , 0)
textView.text = str

But the problem is I don't know how to achieve both together.

I obviously want to remove the square bracket after have applied the highlight effect but when I do a toString() then a replace() the highlight is removed.

Also, the highlight is made with index, and I don't want to extract the substring but let it in the original string, I don't know by which optimized way I should achieve that.

There is the result: enter image description here


Solution

  • Maybe it's better not to use regex in order to extract the texts between close brackets. I think it increases the complexity of this job. Using a simple iteration over the text, we can achieve the result in linear complexity.

    val text = "[Toto] is [doing a lot of] stuff at the same time."
    
    val spanStack = Stack<Pair<Int, Int>>()
    var index = 0
    
    text.forEach {
        when (it) {
            '[' -> spanStack.push(index to index)
            ']' -> spanStack.push(spanStack.pop().first to index)
            else -> index++
        }
    }
    
    val spannableString = text
        .replace("[\\[\\]]".toRegex(), "")
        .let { SpannableString(it) }
        .apply {
            spanStack.forEach {
                setSpan(
                    BackgroundColorSpan(Color.YELLOW),
                    it.first,
                    it.second,
                    SpannableString.SPAN_INCLUSIVE_INCLUSIVE
                )
            }
        }
    
    textView.text = spannableString
    

    Result: