Skip to content

Instantly share code, notes, and snippets.

@dostalleos
Last active September 28, 2020 07:27
Show Gist options
  • Save dostalleos/ea2d218cffa6be3476246e17564a88b0 to your computer and use it in GitHub Desktop.
Save dostalleos/ea2d218cffa6be3476246e17564a88b0 to your computer and use it in GitHub Desktop.
sealed class TextRes {
abstract val resId: Int
data class Regular(
override val resId: Int
) : TextRes() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Regular) return false
if (resId != other.resId) return false
return true
}
override fun hashCode(): Int {
return resId
}
}
class Quantity(
override val resId: Int,
val quantity: Int,
vararg values: Any?
) : TextRes() {
val args = values
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Quantity) return false
if (resId != other.resId) return false
if (quantity != other.quantity) return false
if (!args.contentEquals(other.args)) return false
return true
}
override fun hashCode(): Int {
var result = resId
result = 31 * result + quantity
result = 31 * result + args.contentHashCode()
return result
}
}
class Formatted(
override val resId: Int,
vararg values: Any?
) : TextRes() {
val args = values
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Formatted) return false
if (resId != other.resId) return false
if (!args.contentEquals(other.args)) return false
return true
}
override fun hashCode(): Int {
var result = resId
result = 31 * result + args.contentHashCode()
return result
}
}
}
@SuppressWarnings("SpreadOperator", "NestedBlockDepth")
@BindingAdapter("textRes")
fun TextView.setTextRes(stringRes: TextRes?) {
val newText = when (stringRes) {
is TextRes.Regular -> context.getString(stringRes.resId)
is TextRes.Formatted -> context.getString(stringRes.resId, *stringRes.args)
is TextRes.Quantity -> context.resources.getQuantityString(stringRes.resId, stringRes.quantity, *stringRes.args)
null -> ""
}
val oldText = text
// save layout passes, should apply to all other
if (haveContentsChanged(newText, oldText)) {
text = newText
}
}
@BindingAdapter("textRes")
fun TextView.setTextRes(stringRes: Int?) {
val newText = if (stringRes != null && stringRes != 0) context.getString(stringRes) else ""
val oldText = text
// save layout passes, should apply to all other
if (haveContentsChanged(newText, oldText)) {
text = newText
}
}
@BindingAdapter(value = ["spannableText", "links"], requireAll = true)
fun TextView.setSpannableLinks(spannable: String, links: HashMap<Int, () -> Unit>) {
val span = SpannableStringBuilder(spannable)
for ((link, callback) in links) {
val customSpan = CustomClickableSpan(context, callback, currentTextColor)
val linkSpan = resources.getString(link)
val startLink = spannable.indexOf(linkSpan)
val endLink = startLink + linkSpan.length
if (startLink >= 0) span.setSpan(customSpan, startLink, endLink, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
text = span
}
@SuppressWarnings("ReturnCount")
private fun haveContentsChanged(str1: CharSequence?, str2: CharSequence?): Boolean {
if (str1 == null != (str2 == null)) {
return true
} else if (str1 == null) {
return false
}
val length = str1.length
if (length != str2!!.length) {
return true
}
for (i in 0 until length) {
if (str1[i] != str2[i]) {
return true
}
}
return false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment