如何以指定速度自动滚动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
相关产品推荐
相关产品推荐

