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

如何以指定速度自动滚动TextView?实现片尾字幕式慢速滚动

嘿,我来帮你搞定这个片尾字幕滚动的问题~你之前用Scroller没生效,主要是因为scroller.extendDuration()并不是用来设置初始滚动时长的——它是用来延长已经开始的滚动动画的,所以直接这么用当然没效果啦。

下面给你两种靠谱的实现方案,按需选择:

方法一:用属性动画(推荐,简洁易维护)

属性动画是Android里做平滑过渡最省心的方式,直接操作TextView的滚动位置,代码清晰还不容易踩坑:

// 在Activity的onCreate或合适的生命周期方法中调用
TextView text1 = findViewById(R.id.text1);

// 先计算需要滚动的总距离:文本总高度 - TextView的显示高度
// 注意:要确保TextView已经完成布局,否则getLineCount/getHeight可能返回0
text1.post(() -> {
    int totalTextHeight = text1.getLineCount() * text1.getLineHeight();
    int scrollDistance = totalTextHeight - text1.getHeight();
    
    // 创建滚动动画,从0滚动到目标距离,时长10秒
    ValueAnimator scrollAnimator = ValueAnimator.ofInt(0, scrollDistance);
    scrollAnimator.setDuration(10000); // 10秒,单位毫秒
    scrollAnimator.setInterpolator(new LinearInterpolator()); // 匀速滚动,符合片尾字幕的感觉
    scrollAnimator.addUpdateListener(animation -> {
        int currentScrollY = (int) animation.getAnimatedValue();
        text1.scrollTo(0, currentScrollY);
    });
    scrollAnimator.start();
});

为什么用post()?

刚启动Activity时,TextView的宽高和文本布局还没计算完成,直接获取getLineCount()或getHeight()会得到0,导致滚动不生效。用post()可以把代码放到UI队列的末尾,等TextView布局完成后再执行。

方法二:正确使用Scroller实现

如果你一定要用Scroller,那得主动触发滚动,还要配合computeScroll()来持续更新滚动位置,具体步骤如下:

第一步:自定义TextView

创建一个继承自AppCompatTextView的类,封装Scroller的逻辑:

public class ScrollingTextView extends androidx.appcompat.widget.AppCompatTextView {
    private Scroller mScroller;

    public ScrollingTextView(Context context) {
        super(context);
        initScroller();
    }

    public ScrollingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initScroller();
    }

    private void initScroller() {
        // 初始化Scroller,用线性插值器保证匀速滚动
        mScroller = new Scroller(getContext(), new LinearInterpolator());
    }

    // 对外暴露启动滚动的方法,参数是滚动时长(毫秒)
    public void startScrollAnimation(int duration) {
        int totalTextHeight = getLineCount() * getLineHeight();
        int scrollDistance = totalTextHeight - getHeight();
        
        // 启动滚动:从(0,0)滚动到(0, scrollDistance),时长duration
        mScroller.startScroll(0, 0, 0, scrollDistance, duration);
        invalidate(); // 触发computeScroll()
    }

    @Override
    public void computeScroll() {
        // 判断滚动是否还在进行
        if (mScroller.computeScrollOffset()) {
            // 更新当前滚动位置
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            // 继续刷新UI,直到滚动完成
            postInvalidateOnAnimation();
        }
    }
}

第二步:在布局和Activity中使用

把布局里的TextView换成自定义的ScrollingTextView,然后在Activity中调用:

ScrollingTextView text1 = findViewById(R.id.text1);
// 同样要等布局完成后再启动
text1.post(() -> text1.startScrollAnimation(10000));
额外注意事项
  • 确保TextView的高度是固定的(比如设置android:layout_height="300dp"或者match_parent),并且文本总高度超过TextView的显示高度——不然没有滚动的空间,自然看不到效果。
  • 如果需要重复滚动,可以在动画结束后重新启动,比如给属性动画加addListener监听onAnimationEnd事件,或者在Scroller的computeScroll里判断滚动完成后重新调用startScroll。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:49:42