Created
June 10, 2023 10:21
-
-
Save oguzhanaslann/39ac005aa177514b869ec252aa261791 to your computer and use it in GitHub Desktop.
This file contains 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
fun TextView.span( | |
spanSubString: String, | |
builderBlock: SpanBuilder.() -> Unit, | |
) { | |
if(spanSubString.isEmpty()) { | |
Log.d(TAG, "span: Spannable string cannot be empty") | |
return | |
} | |
if(text.isEmpty()) { | |
Log.d(TAG, "span: Text cannot be empty") | |
return | |
} | |
if(!text.contains(spanSubString)) { | |
Log.d(TAG, "span: Text must contain the spannable string") | |
return | |
} | |
val spannableString = SpannableString(text) | |
val textOfView = text.toString() | |
val rangeOfSpanText = textOfView.indexRangeOf(spanSubString) | |
rangeOfSpanText?.let { | |
val spanBuilder = SpanBuilder(textView = this) | |
spanBuilder.range = rangeOfSpanText | |
spanBuilder.spannableString = spannableString | |
spanBuilder.builderBlock() | |
text = spannableString | |
} | |
} | |
fun TextView.span( | |
builderBlock: SpanBuilder.() -> Unit, | |
) { | |
val textOfView = text.toString() | |
this.span(textOfView, builderBlock) | |
} | |
class SpanBuilder( | |
private val textView: TextView | |
) { | |
internal var range: Pair<Int, Int>? = null | |
internal var spannableString: SpannableString? = null | |
fun foreground( | |
@ColorInt color: Int, | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
ForegroundColorSpan(color), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun background( | |
@ColorInt color: Int, | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
BackgroundColorSpan(color), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun underline( | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
UnderlineSpan(), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun bulletSpan( | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
gapInPx: Int = BulletSpan.STANDARD_GAP_WIDTH, | |
@ColorInt color : Int = Color.BLACK | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
BulletSpan(gapInPx,color), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun bulletSpan( | |
subString: String, | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
gapInPx: Int = BulletSpan.STANDARD_GAP_WIDTH, | |
@ColorInt color : Int = Color.BLACK | |
) { | |
val range = textView.text.toString().indexRangeOf(subString) | |
range?.let { | |
spannableString?.setSpan( | |
BulletSpan(gapInPx,color), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun insert( | |
text : String, | |
index : Int | |
) { | |
val spannableStringBuilder = SpannableStringBuilder(textView.text) | |
spannableStringBuilder.insert(index,text) | |
} | |
fun bold( | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
StyleSpan(android.graphics.Typeface.BOLD), | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
fun onClick( | |
flag: Int = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE, | |
onClick: (View) -> Unit, | |
) { | |
range?.let { | |
spannableString?.setSpan( | |
object : ClickableSpan() { | |
override fun onClick(p0: View) { | |
onClick(p0) | |
} | |
}, | |
it.first, | |
it.second + 1, | |
flag | |
) | |
} | |
} | |
} | |
fun String.indexRangeOf(sub: String): Pair<Int, Int>? { | |
val start = indexOf(sub) | |
return when (start != -1) { | |
true -> Pair(start, start + sub.length - 1) | |
false -> null | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment