需求要用到类似于抖音的#话题输入功能,简单记录一下~ 代码比较简单,仅实现了话题文本的颜色渲染,有其他需求直接加代码即可
实现效果:
代码:
import android.content.Context
import android.text.Editable
import android.text.Spannable
import android.text.SpannableString
import android.text.TextWatcher
import android.text.style.ForegroundColorSpan
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.content.ContextCompat
class TopicEditText(context: Context, attrs: AttributeSet) : AppCompatEditText(context, attrs) {
private val topicRegex = "#[\p{L}0-9_]+".toRegex() // 匹配话题的正则表达式
private val topicColor = ContextCompat.getColor(context, R.color.theme) // 话题的主题色
private var handlingTopic = false // 是否正在处理话题文本的标志位
init {
// 监听文本变化
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (!handlingTopic) {
handlingTopic = true
handleTopicText(s, start, count)
handlingTopic = false
}
}
override fun afterTextChanged(s: Editable?) {}
})
}
private fun handleTopicText(s: CharSequence?, start: Int, count: Int) {
s ?: return
val end = start + count
val matcher = topicRegex.toPattern().matcher(s)
while (matcher.find()) {
val topicStart = matcher.start()
val topicEnd = matcher.end()
if (topicStart < end && topicEnd > start) {
// 匹配到话题
val span = ForegroundColorSpan(topicColor)
val spannable = SpannableString(s)
spannable.setSpan(span, topicStart, topicEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setText(spannable)
setSelection(end) // 保持光标位置不变
break
}
}
}
}