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.
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)
}
}
}