135 lines
4.1 KiB
Kotlin
135 lines
4.1 KiB
Kotlin
package com.gh.common.util
|
|
|
|
import android.content.Context
|
|
import android.graphics.Color
|
|
import android.text.Spannable
|
|
import android.text.SpannableStringBuilder
|
|
import android.text.Spanned
|
|
import android.text.TextPaint
|
|
import android.text.method.LinkMovementMethod
|
|
import android.text.style.ClickableSpan
|
|
import android.text.style.ForegroundColorSpan
|
|
import android.text.style.UnderlineSpan
|
|
import android.view.View
|
|
import android.widget.TextView
|
|
import androidx.annotation.StringRes
|
|
import androidx.core.content.ContextCompat
|
|
|
|
/**
|
|
* @author : liujiarui
|
|
* date : 2023/3/22
|
|
* description : 文本颜色事件控制
|
|
*/
|
|
//作用域进行限制
|
|
@DslMarker
|
|
@Target(AnnotationTarget.TYPE)
|
|
annotation class TextSpanDsl
|
|
|
|
interface DslSpannableStringBuilder {
|
|
//增加一段文字
|
|
fun addText(text: String, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)? = null)
|
|
fun addText(@StringRes stringRes: Int, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)? = null)
|
|
}
|
|
|
|
interface DslSpanBuilder {
|
|
//设置文字颜色文本
|
|
fun setColor(color: String)
|
|
|
|
//设置文字颜色int
|
|
fun setColor(color: ColorInt)
|
|
|
|
//设置文字颜色id
|
|
fun setColor(color: ColorResId)
|
|
|
|
//设置点击事件
|
|
fun onClick(useUnderLine: Boolean = false, onClick: (View) -> Unit)
|
|
}
|
|
|
|
//为 TextView 创建扩展函数,其参数为接口的扩展函数
|
|
fun TextView.buildSpannableString(init: @TextSpanDsl DslSpannableStringBuilder.() -> Unit) {
|
|
//具体实现类
|
|
val spanStringBuilderImpl = DslSpannableStringBuilderImpl(context)
|
|
spanStringBuilderImpl.init()
|
|
movementMethod = LinkMovementMethod.getInstance()
|
|
//通过实现类返回SpannableStringBuilder
|
|
text = spanStringBuilderImpl.build()
|
|
}
|
|
|
|
class DslSpannableStringBuilderImpl(val context: Context) : DslSpannableStringBuilder {
|
|
private val builder = SpannableStringBuilder()
|
|
|
|
//记录上次添加文字后最后的索引值
|
|
private var lastIndex: Int = 0
|
|
var isClickable = false
|
|
|
|
override fun addText(text: String, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)?) {
|
|
val start = lastIndex
|
|
builder.append(text)
|
|
lastIndex += text.length
|
|
val spanBuilder = DslSpanBuilderImpl(context)
|
|
method?.let { spanBuilder.it() }
|
|
spanBuilder.apply {
|
|
onClickSpan?.let {
|
|
builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
isClickable = true
|
|
}
|
|
if (!useUnderLine) {
|
|
val noUnderlineSpan = NoUnderlineSpan()
|
|
builder.setSpan(noUnderlineSpan, start, lastIndex, Spanned.SPAN_MARK_MARK)
|
|
}
|
|
foregroundColorSpan?.let {
|
|
builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun addText(stringRes: Int, method: (@TextSpanDsl DslSpanBuilder.() -> Unit)?) {
|
|
val text = context.getString(stringRes)
|
|
addText(text, method)
|
|
}
|
|
|
|
fun build(): SpannableStringBuilder {
|
|
return builder
|
|
}
|
|
}
|
|
|
|
class DslSpanBuilderImpl(val context: Context) : DslSpanBuilder {
|
|
var foregroundColorSpan: ForegroundColorSpan? = null
|
|
var onClickSpan: ClickableSpan? = null
|
|
var useUnderLine = true
|
|
|
|
override fun setColor(color: String) {
|
|
foregroundColorSpan = ForegroundColorSpan(Color.parseColor(color))
|
|
}
|
|
|
|
override fun setColor(color: ColorInt) {
|
|
foregroundColorSpan = ForegroundColorSpan(color.color)
|
|
}
|
|
|
|
override fun setColor(color: ColorResId) {
|
|
val c = ContextCompat.getColor(context, color.colorResId)
|
|
foregroundColorSpan = ForegroundColorSpan(c)
|
|
}
|
|
|
|
override fun onClick(useUnderLine: Boolean, onClick: (View) -> Unit) {
|
|
onClickSpan = object : ClickableSpan() {
|
|
override fun onClick(widget: View) {
|
|
onClick(widget)
|
|
}
|
|
}
|
|
this.useUnderLine = useUnderLine
|
|
}
|
|
}
|
|
|
|
@JvmInline
|
|
value class ColorInt(val color: Int)
|
|
|
|
@JvmInline
|
|
value class ColorResId(val colorResId: Int)
|
|
|
|
class NoUnderlineSpan : UnderlineSpan() {
|
|
override fun updateDrawState(ds: TextPaint) {
|
|
ds.color = ds.linkColor
|
|
ds.isUnderlineText = false
|
|
}
|
|
} |