如何在ScrollView滚动时实现TextView文本大小动态调整动画
实现ScrollView滚动时TextView字号平滑缩放
问题说明
我有一个位于ScrollView外部的TextView,需求是:
- 向下滚动ScrollView时,TextView字号逐渐缩小到最小15sp
- 向上滚动时,字号恢复至初始的25sp
尝试过两种方法但效果不佳:
- 在ScrollListener的
onScroll方法中每次调整0.01f字号,动画不流畅 - 使用
setAutoSizeTextTypeUniformWithConfiguration(12,25, 2,TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM),但该方法用于文本适配容器大小,不适合滚动驱动的字号变化,调整逻辑不符合需求
TextView布局代码:
<TextView android:id="@+id/t1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:fontFamily="@font/poppins" android:text="Some text" android:textColor="@color/black" android:textSize="25sp" android:textStyle="bold" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@id/cons1" />
解决方案
核心思路是根据ScrollView的滚动比例,计算TextView的目标字号,通过比例映射+直接赋值实现流畅动画,避免逐帧微调的卡顿。
步骤1:实现滚动监听与字号计算
// 获取控件实例 ScrollView scrollView = findViewById(R.id.your_scroll_view); TextView textView = findViewById(R.id.t1); // 转换字号为px,避免屏幕密度差异导致的单位混乱 final float initialSizePx = getResources().getDimension(R.dimen.text_size_25sp); final float minSizePx = getResources().getDimension(R.dimen.text_size_15sp); // 监听ScrollView布局完成,确保能获取正确的滚动范围 scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this); // 计算可滚动总高度:内容高度 - ScrollView自身可见高度 final int scrollRange = scrollView.getChildAt(0).getHeight() - scrollView.getHeight(); scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { if (scrollRange <= 0) return; // 计算滚动比例,限制在0-1区间 float scrollRatio = Math.max(0f, Math.min(1f, (float) scrollY / scrollRange)); // 根据比例计算目标字号:初始值按比例递减到最小值 float targetSizePx = initialSizePx - (initialSizePx - minSizePx) * scrollRatio; // 直接赋值,系统会自动处理绘制平滑度 textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, targetSizePx); } }); } });
步骤2:添加统一管理的dimen资源(可选)
在res/values/dimens.xml中定义字号,方便后续修改:
<dimen name="text_size_25sp">25sp</dimen> <dimen name="text_size_15sp">15sp</dimen>
关键注意事项
- 不要在
onScroll中逐帧微调字号(比如每次±0.01f),这种方式会触发频繁重绘,导致卡顿 setAutoSizeTextTypeUniformWithConfiguration是用于文本适配容器宽高的,和滚动驱动的字号变化逻辑不匹配,不适用此场景- 必须将sp转为px计算,避免不同屏幕密度下的显示偏差
- 必须等待ScrollView布局完成后再计算滚动范围,否则获取的高度会不准确
内容的提问来源于stack exchange,提问作者mikegrep
相关产品推荐
相关产品推荐

