最近接到个需求,在一段英文中,将给定的单词高亮。写了近1天,考虑了各种情况,终于写完了对应算法。我将其封装成一个:MySpanTextView
源码在下面,直接复制,拿到项目中用就行。继承自普通TextView,仅仅对文字匹配做了修改,其他属性不变。复制代码,可以直接用
需求:给定一段英文,和某些关键字,在英文中,将关键字高亮。
要求:将给定的关键字视为独立的单词,当其出现在其他单词内时,不可以高亮。
如:
关键字中有单独字母 a ,则 and、teacher等单词中的 a 不可以高亮
英文中有一个单词是 haha ,关键字中有一个是 ha,则 haha 中,ha 不可以高亮
效果图如下:
相关的注释,全部在代码中了
/**
* 展示高亮关键字的TextView
*/
class MySpanTextView : TextView {
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
/**
* 设置文字前景色
*
* content 要展示的文字
* highlight 要处理为高亮的所有关键字
*/
fun setTextForegColor(content: String?, highlight: String?, tip: String?) {
try {
//如果文本为空,就 setText=""
if (content.isNullOrEmpty()) {
text = ""
return
}
//如果文本为空,就 setText=content
if (highlight.isNullOrEmpty()) {
text = content
return
}
/**
* 整体思路
*
* 1、将全部的高亮关键字(keys),进行切分,拿到单个的关键字(key)
* 2、用每个key,去原始文本中进行遍历,找到出现的位置(每次出现的位置)
* 3、对该位置的前后进行判断,是否是有效的单词分隔符,如:空格、逗号、句号等
* 4、如果符合条件,就是最终,要高亮的位置(有效位),这个位置上的单词,就是要高亮的单词
*
* 如:
* 原始文本:abc is a Teacher.
* 高亮单词:a
* 结果:abc、Teacher 中的"a",不能高亮,只有单独的那个"a",才能高亮,单独的"a"出现的位置,才是真正的有效位
* 理由:abc中,虽然可以找到a,但是a后面,是"b",不是单词分隔符,所有不能算有效位
*
* 关于位置的处理思路:
* 目前,找到后,先存起来(封装成一个bean(index:出现位置,key:key的内容),最后整体遍历一遍;