如何在SpannableString中查找指定子字符串的索引位置
SpannableString 不转换为普通字符串查找子串索引的实现方案
SpannableString 原生实现了 CharSequence 接口,本身支持直接读取内部字符做匹配,无需转换为普通 String 执行查找。以下是两种可直接使用的实现方案:
方案1:自定义轻量匹配方法
直接基于 CharSequence 接口做字符遍历匹配,无额外依赖,性能最优:
// Kotlin 扩展方法实现,可直接对 SpannableString 调用 fun CharSequence.indexOf( sub: CharSequence, startIndex: Int = 0, ignoreCase: Boolean = false ): Int { val subLength = sub.length if (subLength == 0) return if (startIndex in indices) startIndex else length val firstChar = sub[0] var currentPos = startIndex val maxSearchPos = length - subLength while (currentPos <= maxSearchPos) { // 匹配首字符 if (!charEquals(this[currentPos], firstChar, ignoreCase)) { currentPos++ while (currentPos <= maxSearchPos && !charEquals(this[currentPos], firstChar, ignoreCase)) { currentPos++ } } // 首字符匹配后校验剩余字符 if (currentPos <= maxSearchPos) { var subPos = 1 var sourcePos = currentPos + 1 val endPos = currentPos + subLength while (sourcePos < endPos && charEquals(this[sourcePos], sub[subPos], ignoreCase)) { sourcePos++ subPos++ } if (sourcePos == endPos) return currentPos } currentPos++ } return -1 } private fun charEquals(c1: Char, c2: Char, ignoreCase: Boolean): Boolean { return if (ignoreCase) c1.equals(c2, ignoreCase = true) else c1 == c2 }
使用示例:
val formattedSpannable = SpannableString("带自定义格式的测试文本内容") val targetSub = "测试文本" val startIndex = formattedSpannable.indexOf(targetSub) // 匹配成功返回起始索引,失败返回-1
方案2:借助系统正则匹配工具实现
如果需要支持正则匹配能力,可直接使用系统Pattern、Matcher工具,原生支持传入CharSequence类型参数:
// Java 实现示例 import java.util.regex.Pattern; import java.util.regex.Matcher; SpannableString formattedSpannable = new SpannableString("带自定义格式的测试文本内容"); String targetSub = "测试文本"; // 用Pattern.quote包裹目标子串,避免子串含正则特殊字符时匹配异常 Pattern pattern = Pattern.compile(Pattern.quote(targetSub)); Matcher matcher = pattern.matcher(formattedSpannable); if (matcher.find()) { int startIndex = matcher.start(); // 子串起始索引 int endIndex = matcher.end(); // 子串结束索引(不含) }
两种方案均不会触发SpannableString到普通String的转换,匹配逻辑完全不受SpannableString上绑定的样式Span影响,返回的索引结果和普通String的indexOf方法返回结果一致。
内容的提问来源于stack exchange,提问作者Tamzid
相关产品推荐
相关产品推荐

