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

Android TextView权重与跑马灯:其他View更新时跑马灯重置问题求助

问题描述

我有一个水平方向的LinearLayout,内部包含两个TextView,要求它们始终可见。第一个TextView文本长度不固定,需要适配两种显示场景:

  • 当第一个文本较长时:|[text1 long long lo...][text2]|
  • 当第一个文本较短时:|[text1][text2]_______________|

我给第一个TextView设置了永久跑马灯动画,用layout_weight适配长文本场景,同时把LinearLayout宽度设为wrap_content适配短文本场景。但现在遇到问题:更新第二个TextView时,第一个TextView的跑马灯动画会重置,不符合需求。求可行的修复方案。

示例代码

<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textViewFirst"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:fontFamily="@font/roboto_regular"
        android:textSize="32sp"
        android:text="May be a very very very long text view"
        android:lineHeight="37.504dp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever" />
    <TextView
        android:id="@+id/textViewSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/transparentWhite"
        android:fontFamily="@font/roboto_regular"
        android:textSize="32sp"
        android:text=" short text"
        android:lineHeight="37.504dp" />

</LinearLayout>

修复方案

方案1:自定义TextView控制跑马灯状态

系统默认TextView在布局重绘时会重置跑马灯,自定义一个MarqueeTextView手动管控状态,避免被布局更新打断:

class MarqueeTextView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextView(context, attrs, defStyleAttr) {

    private var isMarqueeRunning = false

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (isMarqueeRunning) startMarquee()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        isMarqueeRunning = isFocused && marquee != null && marquee.isRunning
    }

    fun startMarqueeManually() {
        isMarqueeRunning = true
        ellipsize = null
        ellipsize = TextUtils.TruncateAt.MARQUEE
        requestFocus()
    }

    fun stopMarqueeManually() {
        isMarqueeRunning = false
        marquee?.stop()
    }
}

布局中替换原TextView为自定义类,初始化时调用startMarqueeManually()启动跑马灯,更新第二个TextView时不会影响第一个的动画状态。

方案2:调整LinearLayout布局参数避免重绘触发重置

原LinearLayout设为wrap_content,更新第二个TextView会触发整体布局重绘,改成match_parent并给第一个TextView动态设置maxWidth:

  1. 将LinearLayout的android:layout_width改为match_parent
  2. 动态计算第一个TextView的最大宽度:
textViewSecond.post {
    val parentWidth = linearLayout.width
    val secondTextWidth = textViewSecond.width
    textViewFirst.maxWidth = parentWidth - secondTextWidth - dpToPx(16) // 减去预留间距
}

这种方式减少布局重绘对第一个TextView的干扰,跑马灯不会被轻易重置,同时也能满足两种显示场景。

方案3:用ConstraintLayout替代LinearLayout

ConstraintLayout布局更新更高效,可精准控制两个TextView的关系,避免weight机制带来的重绘问题:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textViewFirst"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:fontFamily="@font/roboto_regular"
        android:textSize="32sp"
        android:text="May be a very very very long text view"
        android:lineHeight="37.504dp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/textViewSecond"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintWidth_max="wrap" />

    <TextView
        android:id="@+id/textViewSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/transparentWhite"
        android:fontFamily="@font/roboto_regular"
        android:textSize="32sp"
        android:text=" short text"
        android:lineHeight="37.504dp"
        app:layout_constraintStart_toEndOf="@id/textViewFirst"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

该布局既满足长文本压缩显示跑马灯、短文本靠左排列的需求,又能避免更新第二个TextView时重置第一个的跑马灯。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:30:33