javaandroidkotlinandroid-edittextspannable

How to remove a part of Spannable


In my android app user can change text foreground and background colors by selecting text, everything works fine, but if user created red foreground for text Hello World, and wants to remove red foreground in the World word, code removes the whole sentence background, if there's a way to do it, please, help me, here is the function:

private fun changeTextForegroundColor(

        @ColorInt foregroundColor: Int?,

        startPosition: Int,

        endPosition: Int

    ) {

        val resultText: Spannable = bindingContent.contentEditText.text.toSpannable()

        //Get foreground spans and remove them.

        val spans: Array<ForegroundColorSpan> = resultText.getSpans(

                startPosition, endPosition,

                ForegroundColorSpan::class.java)

        repeat(spans.count()) {

            resultText.removeSpan(spans[it])

        }

        

        // If foregroundColor == null, then just remove the span, what we do above

        if (foregroundColor != null) {

            resultText.setSpan(

                    ForegroundColorSpan(foregroundColor),

                    startPosition,

                    endPosition,

                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

            

        }

        bindingContent.contentEditText.setText(resultText)

        

    }

I tried not to remove, but to replace the foreground color with white(my text color) but it causes lags in my app, so I need to remove a word World, without removing the Hello word foreground in my span.


Solution

  • Finally, I wrote code that as I guess can resolve my problem, here I remove spans if span within selection (It won't remove span which range outside of selection), then check if color is null, then set color to white, else to another one. This code helps to to avoid issue when one span was painted over another one:

    private fun changeTextForegroundColor( @ColorInt foregroundColor: Int?, startPosition: Int, endPosition: Int) {
        val resultText: Spannable =
            noteBinding.contentActivityInclude.contentEditText.text?.toSpannable() ?: return
        
        val spans: Array<ForegroundColorSpan> = resultText.getSpans(
                startPosition, endPosition,
                ForegroundColorSpan::class.java)
        spans.forEach {
            val selectedSpanStart = resultText.getSpanStart(it)
            val selectedSpanEnd = resultText.getSpanEnd(it)
            if (selectedSpanStart >= startPosition && selectedSpanEnd <= endPosition) {
                
                resultText.removeSpan(it)
                
            }
            
        }
        if (foregroundColor == null) {
            resultText.setSpan(
                    ForegroundColorSpan(Color.WHITE),
                    startPosition,
                    endPosition,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        } else {
            resultText.setSpan(
                    ForegroundColorSpan(foregroundColor),
                    startPosition,
                    endPosition,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            
        }
        
        noteBinding.contentActivityInclude.contentEditText.setText(resultText)
        
    }