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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:46:16