Android自定义滚动TextView文本被裁剪,如何完整显示全部内容?
Android自定义滚动TextView文本被布局宽度裁剪问题
我正在构建一个滚动文本的Demo,为了获得更强的控制能力,不使用系统自带的marquee效果。目前遇到的问题是:TextView中的长文本被布局宽度裁剪,尝试多种方法均无法解决。
布局代码
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/frame_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:clipChildren="false" android:clipToPadding="false" tools:context=".MainActivity"> </FrameLayout>
MainActivity核心代码
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FrameLayout fl = (FrameLayout) findViewById(R.id.frame_layout); TextView scrollingText = new TextView(this); scrollingText.setText(R.string.long_content); scrollingText.setTextColor(Color.WHITE); scrollingText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 32); scrollingText.setSingleLine(true); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM); scrollingText.setLayoutParams(params); fl.addView(scrollingText); animator = ValueAnimator.ofFloat(1.0f, 0.0f); animator.setDuration(10000); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float progress = (float) valueAnimator.getAnimatedValue(); scrollingText.measure(0, 0); float width = scrollingText.getMeasuredWidth(); float translationX = width*(progress-1); scrollingText.setTranslationX(translationX); } } ); animator.start(); }
调试发现:TextView的getWidth()返回屏幕宽度1024,而getMeasuredWidth()返回文本实际宽度3985,希望实现TextView显示全部文本并正常滚动的效果。
解决方案
问题根源:即使设置了setSingleLine(true),TextView在默认情况下会被父容器的宽度约束,导致文本被裁剪。需要让TextView允许水平方向超出父容器,同时保持完整的文本宽度。
1. 关键修改:添加setHorizontallyScrolling(true)
给TextView添加该方法,它会强制TextView按照文本的实际宽度进行测量,不会将文本裁剪到父容器的宽度内,同时允许水平方向滚动/超出显示:
TextView scrollingText = new TextView(this); // ... 其他设置 scrollingText.setSingleLine(true); scrollingText.setHorizontallyScrolling(true); // 新增这一行
2. 优化动画测量逻辑
避免在动画的每次更新回调中重复测量TextView宽度,提前在动画启动前完成测量,提升性能:
// 在animator.start()之前执行测量 scrollingText.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); final float textWidth = scrollingText.getMeasuredWidth(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float progress = (float) valueAnimator.getAnimatedValue(); float translationX = textWidth * (progress - 1); scrollingText.setTranslationX(translationX); } });
3. 确认父容器裁剪设置
确保FrameLayout的android:clipChildren="false"和android:clipToPadding="false"生效,这样TextView超出父容器的部分不会被裁剪。如果Activity的根布局(比如默认的LinearLayout)也设置了裁剪,需要同步修改。
修改完成后,TextView的getWidth()会和getMeasuredWidth()一致(即文本实际宽度),滚动动画时就能完整显示全部文本,不会被布局宽度裁剪。
内容的提问来源于stack exchange,提问作者Zoran
相关产品推荐
相关产品推荐

