Android使用Span实现Loading尾随圆点动画无效果如何解决
问题原因
你的代码存在3处核心错误导致效果无法实现:
- 类型转换异常:调用
setText时传入的是SpannableStringBuilder实例,但动画回调里强行将textView.text转为SpannableString,会触发运行时异常,后续逻辑全部无法执行,是圆点完全不显示的核心原因。 - Span逻辑错误:仅给需要显示的圆点设置前景色,没有隐藏不需要显示的圆点,无法实现圆点逐个出现的效果。
- 动画配置错误:
repeatCount = 10只会重复10次后停止,无法无限循环;4000ms的总时长也会导致动画切换太慢。
修正后可运行代码
val text = "Loading" // 初始化包含3个圆点的文本 val fullText = "$text..." val spannedText = SpannableStringBuilder(fullText) binding.textViewTitle.setText(spannedText, TextView.BufferType.SPANNABLE) ValueAnimator.ofInt(0, 4).apply { repeatCount = ValueAnimator.INFINITE // 无限循环 repeatMode = ValueAnimator.RESTART // 循环到终点后回到起点重新开始 duration = 1200 // 总时长1.2s,每个状态间隔300ms,可按需调整 addUpdateListener { animator -> val dotsCount = animator.animatedValue as Int val textSpan = binding.textViewTitle.text as SpannableStringBuilder // 先清除旧的前景色Span textSpan.getSpans(0, textSpan.length, ForegroundColorSpan::class.java) .forEach { textSpan.removeSpan(it) } // 把超出当前显示数量的圆点设为透明(如果你的TextView有背景色,也可以换成和背景相同的颜色) if (dotsCount < 3) { textSpan.setSpan( ForegroundColorSpan(Color.TRANSPARENT), text.length + dotsCount, fullText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ) } // 无需手动调用invalidate,修改Span后TextView会自动刷新 } }.start()
关键优化说明
- 统一使用
SpannableStringBuilder处理可编辑Span文本,避免类型转换错误 - 每次动画更新前先清除旧Span,避免多个Span叠加导致效果异常
- 通过将不需要显示的圆点设为透明实现隐藏效果,无需频繁修改文本内容,性能更高
内容的提问来源于stack exchange,提问作者Henrique Vasconcellos
相关产品推荐
相关产品推荐

