Skip to content

Instantly share code, notes, and snippets.

@radoyankov
Last active January 27, 2023 08:59
Show Gist options
  • Save radoyankov/29833fc1f5ecd577b0581d6de93ff60f to your computer and use it in GitHub Desktop.
Save radoyankov/29833fc1f5ecd577b0581d6de93ff60f to your computer and use it in GitHub Desktop.
Easy Spannable on Kotlin
val spanned = spannable{ bold("some") + italic(" formatted") + color(Color.RED, " text") }
val nested = spannable{ bold(italic("nested ")) + url("www.google.com", "text") }
val noWrapping = bold("no ") + sub("wrapping ) + sup("also ") + "works"
text_view.text = spanned + nested + noWrapping
import android.text.Spannable
import android.text.SpannableString
import android.text.TextUtils
import android.text.style.*
fun spannable(func: () -> SpannableString) = func()
private fun span(s: CharSequence, o: Any) = (if (s is String) SpannableString(s) else s as? SpannableString
?: SpannableString("")).apply { setSpan(o, 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) }
operator fun SpannableString.plus(s: SpannableString) = SpannableString(TextUtils.concat(this, s))
operator fun SpannableString.plus(s: String) = SpannableString(TextUtils.concat(this, s))
fun bold(s: CharSequence) = span(s, StyleSpan(android.graphics.Typeface.BOLD))
fun italic(s: CharSequence) = span(s, StyleSpan(android.graphics.Typeface.ITALIC))
fun underline(s: CharSequence) = span(s, UnderlineSpan())
fun strike(s: CharSequence) = span(s, StrikethroughSpan())
fun sup(s: CharSequence) = span(s, SuperscriptSpan())
fun sub(s: CharSequence) = span(s, SubscriptSpan())
fun size(size: Float, s: CharSequence) = span(s, RelativeSizeSpan(size))
fun color(color: Int, s: CharSequence) = span(s, ForegroundColorSpan(color))
fun background(color: Int, s: CharSequence) = span(s, BackgroundColorSpan(color))
fun url(url: String, s: CharSequence) = span(s, URLSpan(url))
@gonztirado
Copy link

gonztirado commented Mar 26, 2021

Thanks for all you guys! I'm using @Scorpio93 implementation, very nice job!

I also added a two more extensions for ClickableSpan:

/** You will need set movementMethod = LinkMovementMethod.getInstance() in the TextView to allow clicking on the span */
fun CharSequence.clickable(listener: View.OnClickListener) : SpannableString {
    val clickSpan = object : ClickableSpan() {
        override fun onClick(widget: View) {
            listener.onClick(widget)
        }
    }
    return span(this, clickSpan)
}
/** You will need set movementMethod = LinkMovementMethod.getInstance() in the TextView to allow clicking on the span */
fun CharSequence.clickableWithoutUnderline(listener: View.OnClickListener) : SpannableString {
    val clickSpan = object : ClickableSpan() {
        override fun onClick(widget: View) {
            listener.onClick(widget)
        }
        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.isUnderlineText = false
        }
    }
    return span(this, clickSpan)
}

@luckerbai
Copy link

Nice job~Thanks for all you guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment