思路用正则匹配#和@然后刷新改变UI
private val inputReg = "([#|@][\u4e00-\u9fa5a-zA-Z\\d_|-]+\\d{0,100})"
在onTextChanged或者afterTextChanged中进行匹配
if (s.isNullOrEmpty()) return val pattern = Pattern.compile(inputReg) //赋值话题列表数据 val matcher = pattern.matcher(s.toString()) topicList.clear() while (matcher.find()) { // "${matcher.start().logE()} - ${matcher.end()}".logE() topicList.add( s.toString().substring(matcher.start(), matcher.end()) ) } //刷新页面 reFreshText(s.toString())
保存匹配到话题进行保存,然后刷新UI
private fun reFreshText(content: String) { if (topicList.isNullOrEmpty()) return // 重新设置span val editable = text?:return var colorSpan = ForegroundColorSpan(Color.parseColor("#333333")) editable.setSpan( colorSpan, 0, text.toString().length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) val textLength = editable.length var findPosition = 0 topicList.forEach { objectText -> for (i in 0 until textLength) { while (findPosition <= textLength) { findPosition = content.indexOf(objectText, findPosition) if (findPosition != -1) { // 设置话题内容前景色高亮 var colorSpan = ForegroundColorSpan(topic_text_color) editable.setSpan( colorSpan, findPosition, findPosition + objectText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) findPosition += objectText.length } else { break } } } } }
这里懒了一些,直接循环了,改成继续正则匹配保存的内容会比较好一点。
另外自定义textview展示也可以这样操作,核心代码
private fun getTextSpan(content: String): SpannableString { val spannableString = SpannableString(content) if (content.isNotEmpty()) { val pattern = Pattern.compile("([#|@][\u4e00-\u9fa5a-zA-Z\\d_|-]+\\d{0,100})") val matcher = pattern.matcher(content) while (matcher.find()) { var colorSpan = ForegroundColorSpan(topic_text_color) spannableString.setSpan( colorSpan, matcher.start() ?: 0, matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) } } return spannableString }
参考这段代码用于改造自定义EditTextView的刷新会比较好一点