You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:ScrollView在子TextView修改Span时停止滚动的问题

解决ScrollView因TextView Span更新停止滚动的问题

我来帮你搞定这个头疼的问题~ 当你每秒更新TextView里的Span时,ScrollView会停止滚动,本质原因是Span的修改会触发TextView的内容变更通知,ScrollView会误以为内容发生了实质性变化,从而重置滚动状态。下面是具体的解决步骤和代码优化方案:

核心思路

在更新Span前后,手动保存并恢复ScrollView的滚动位置,避免系统自动重置滚动状态。同时,别忘了清理旧的Span,避免性能问题和显示异常。

1. 保存并恢复滚动位置

修改你的onUpdateTime Runnable,在更新Span前记录当前滚动位置,更新完成后再恢复:

private Runnable onUpdateTime = new Runnable() {
    @Override
    public void run() {
        // 1. 保存当前ScrollView的滚动位置
        int savedScrollY = m_scrollView.getScrollY();
        
        // 2. 执行Span更新操作
        changeTextViewSpan();
        
        // 3. 恢复滚动位置,用post确保在视图更新后执行,避免无效操作
        m_scrollView.post(() -> {
            m_scrollView.scrollTo(0, savedScrollY);
        });
        
        m_mainLayout.postDelayed(onUpdateTime, 1000);
    }
};

2. 清理旧Span避免叠加

每次设置新Span前,先移除之前的下划线Span,不然Span会不断累积,既影响性能也可能导致显示错误:

private void changeTextViewSpan() {
    // 先移除已存在的下划线Span
    m_spannableText.removeSpan(m_underlineSpan);
    // 再设置新的Span范围
    m_spannableText.setSpan(
        m_underlineSpan, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

额外优化建议

如果你的场景需要支持用户手动滚动时不被恢复操作打断,可以添加滚动状态判断:

  • 给ScrollView设置OnScrollChangeListener,记录是否处于用户手动滚动状态
  • 在恢复滚动位置前,判断如果不是用户手动滚动,再执行恢复操作

示例代码(可选):

private boolean isUserScrolling = false;

// 在onCreate里设置滚动监听
m_scrollView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
    // 判断是否是用户手动滚动(简单判断:滚动前后位置变化,且不是代码触发的滚动)
    isUserScrolling = scrollY != oldScrollY;
});

// 然后在恢复滚动位置时判断
m_scrollView.post(() -> {
    if (!isUserScrolling) {
        m_scrollView.scrollTo(0, savedScrollY);
    }
});

这样就能完美解决Span更新导致ScrollView停止滚动的问题啦~

内容的提问来源于stack exchange,提问作者arek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:40:00