Created
March 25, 2022 18:26
-
-
Save muehlemann/2fd10123b8f77f1c5c463829e03e098e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package // TODO: Your Package Here | |
import android.content.Context | |
import android.text.* | |
import android.text.Annotation | |
import android.text.style.CharacterStyle | |
import android.text.style.ClickableSpan | |
import android.view.View | |
import androidx.annotation.ColorInt | |
import androidx.annotation.StringRes | |
class StyleUtil { | |
open class Style(open val key: String) { | |
data class Bold(override val key: String, val isBold: Boolean) : Style(key) | |
data class Underline(override val key: String, val isUnderlined: Boolean) : Style(key) | |
data class ForegroundColor(override val key: String, @ColorInt val color: Int) : Style(key) | |
data class BackgroundColor(override val key: String, @ColorInt val color: Int) : Style(key) | |
} | |
interface Listener { | |
fun styleClicked(key: String) | |
} | |
class Builder { | |
private var text: Spannable = SpannableStringBuilder("") | |
private var styles: List<Style> = emptyList() | |
private var listener: Listener? = null | |
fun text(context: Context, @StringRes res: Int) = apply { this.text = SpannableStringBuilder(context.getText(res)) } | |
fun styles(styles: List<Style>) = apply { this.styles = styles } | |
fun listener(listener: Listener) = apply { this.listener = listener } | |
fun build(): Spannable { | |
val annotations = text.getSpans(0, text.length, Annotation::class.java) | |
for (annotation in annotations) { | |
text.setSpan( | |
generateSpans(annotation.value, styles, listener), | |
text.getSpanStart(annotation), | |
text.getSpanEnd(annotation), | |
text.getSpanFlags(annotation) | |
) | |
} | |
return text | |
} | |
private fun generateSpans(key: String, styles: List<Style>, listener: Listener?): CharacterStyle { | |
return object : ClickableSpan() { | |
override fun onClick(view: View) { | |
listener?.styleClicked(key) | |
} | |
override fun updateDrawState(textPaint: TextPaint) { | |
for (style in styles) { | |
if (key == style.key) { | |
when (style) { | |
is Style.Bold -> textPaint.isFakeBoldText = style.isBold | |
is Style.BackgroundColor -> textPaint.bgColor = style.color | |
is Style.ForegroundColor -> textPaint.color = style.color | |
is Style.Underline -> textPaint.isUnderlineText = style.isUnderlined | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
StyleUtil
Spans are great but can be a pain to work with in applications that are localized. The main reason for this is that in different localizations the start and stop indexes for a span will differ. The following class allows you to apply some basic styles along with a
styleClicked(key: String)
callback, to strings loaded from XML that utilize the annotation tag.strings.xml
example.kt