0

I've added a strike-through to CompoundButton. The gist of how I'm adding the strike-through is:

fun CompoundButton.addStrikeThrough() {
    val span = SpannableString(text)
    span.setSpan(
        StrikethroughSpan(),
        0,
        text.length,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    text = span
}

I'm using Spannable because I don't always want the entire text striked through. The CompoundButton is actually a CheckBox that strikes through the text when checked. I'm using the above method in a list of CheckBox items and setting a listener inside onBindViewHolder.

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val todoText = todos[position]
    holder.checkBox.apply {
        isChecked = false
        text = todoText
        setOnCheckedChangeListener { checkBox, isChecked ->
            if (isChecked) {
                checkBox.addStrikeThrough()
            } else {
                // how do I write this?
                checkBox.removeStrikeThrough()
            }
        }
    }
}

When I remove and then add another item to the list, I have do deal with recycling of views - leaving me with strike-throughs on items that have been recycled.

How do I remove the strike-through from the CheckBox?

I tried getting the text from the CheckBox and casting it to Spannable, and SpannableString so that I can call removeSpan(), but the text is never an instance of either of those two classes.

I've seen one or two question that are about the same, but their answers do not work.

methodsignature
  • 4,152
  • 2
  • 20
  • 21

1 Answers1

1

You can change your code a little bit and get something like this:

fun CompoundButton.setText(buttonText: String, withStrike: Boolean) {

    text = if (withStrike) {
        val span = SpannableString(buttonText)
        span.setSpan(
                StrikethroughSpan(),
                0,
                text.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        span
    } else {
        buttonText
    }
}

And in your adapter:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val todoText = todos[position]
    holder.checkBox.apply {
        isChecked = false
        text = todoText
        setOnCheckedChangeListener { checkBox, isChecked ->
            checkBox.setText(todoText, isChecked)
        }
    }
}
Vasyl Glodan
  • 556
  • 1
  • 6
  • 22
  • I'm actually doing some animations during this process. The code I posted is a bit stripped down, but I guess still bloated. I'm wondering if Based on your code, maybe I have some other issue causing `text = todoText` to update appropriately... probably based no animations or how I'm adding and removing items. I'll investigate and mark this answer as accepted if it's as simple as updating text. to non-spannable value. – methodsignature Mar 29 '18 at 17:32
  • Sorry for the delay. This is a side project for experimentation and it took me a bit to get back to it. Setting the text to a non-spanned text does remove any spans set on a previous text. Marked answer accordingly. – methodsignature Apr 03 '18 at 11:34