Kotlin循环调用SpannableString.setSpan仅最后一个样式生效问题
问题根因
只有最后一个索引位置的运算符变蓝,是因为你遍历索引设置样式时复用了同一个ForegroundColorSpan实例。
Android Spannable 机制的默认逻辑是:同一个Span对象多次调用setSpan绑定到不同文本区间时,会自动清除该Span之前绑定的所有区间,最终只保留最后一次设置的位置,这和你用SpannableString还是SpannableStringBuilder没有关系。你确认索引数组逻辑正确但只有最后一个生效,完全符合这个问题的特征。
修复方法
遍历每个运算符索引时,为每个位置单独新建一个ForegroundColorSpan实例即可,参考实现代码:
// 以下为核心实现逻辑,替换你原有设置Span的部分即可 val displayContent = calculatorDisplay.text.toString() val spannableStr = SpannableString(displayContent) val operatorBlue = Color.BLUE // 可替换为你需要的具体蓝色色值 operationsInStrings.forEach { opIndex -> // 关键:每次循环新建独立的Span实例,不要在循环外定义后复用 val blueSpan = ForegroundColorSpan(operatorBlue) spannableStr.setSpan( blueSpan, opIndex, opIndex + 1, // 单字符样式区间为[index, index+1),左闭右开 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) } calculatorDisplay.text = spannableStr
避坑提示
- 单字符的样式结束位置必须是索引+1,Spannable的区间是左闭右开规则,传入
opIndex到opIndex不会显示任何样式 - 如果后续有追加、删除文本的操作,要同步更新
operationsInStrings里的索引值,避免索引错位导致样式位置不对 - 用
SpannableStringBuilder实现时逻辑完全一致,只要保证每个绑定位置的Span是独立新建的,就不会出现只生效最后一个的问题
内容的提问来源于stack exchange,提问作者VarS
相关产品推荐
相关产品推荐

