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

Jetpack Compose中如何实现Marquee文本跑马灯滚动效果?

Jetpack Compose 实现文本跑马灯效果方案

方案1:官方原生实现(Compose 1.4.0 及以上推荐)

Compose 从1.4.0-alpha04版本开始内置了跑马灯支持,仅需给Text组件添加basicMarquee修饰符即可实现:

// 需导入compose.foundation的basicMarquee扩展
import androidx.compose.foundation.basicMarquee

Text(
    text = "超长文本超长文本超长文本超长文本超长文本超长文本",
    modifier = Modifier
        .fillMaxWidth()
        .basicMarquee(
            iterations = Int.MAX_VALUE, // 无限滚动
            animationMode = MarqueeAnimationMode.WhileVisible, // 可见时自动滚动
            delayMillis = 1000, // 滚动前停留1秒
            velocity = 30.dp // 滚动速度为每秒30dp
        ),
    maxLines = 1
)

常用参数说明:

  • iterations:滚动重复次数,设置为Int.MAX_VALUE即可实现无限滚动
  • animationMode:滚动触发条件,可选WhileFocused(获得焦点时滚动)、WhileVisible(组件可见时滚动)、Always(始终滚动)
  • delayMillis:每次滚动开始前的等待时长,单位为毫秒
  • velocity:滚动速度,单位为dp/秒

方案2:自定义实现(兼容低版本Compose)

如果项目使用的Compose版本低于1.4.0,可以通过自定义动画修饰符实现:
首先定义跑马灯修饰符:

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.text.TextLayoutResult

fun Modifier.marquee(
    scrollSpeed: Dp = 30.dp,
    delayBeforeScroll: Int = 1000
): Modifier = composed {
    var containerWidth by remember { mutableStateOf(0) }
    var textWidth by remember { mutableStateOf(0) }
    val transition = rememberInfiniteTransition(label = "marquee")

    val scrollOffset by transition.animateFloat(
        initialValue = 0f,
        targetValue = if (textWidth > containerWidth) -(textWidth - containerWidth).toFloat() else 0f,
        animationSpec = infiniteRepeatable(
            animation = tween(
                durationMillis = ((textWidth - containerWidth) / scrollSpeed.value * 1000).toInt(),
                delayMillis = delayBeforeScroll,
                easing = LinearEasing
            ),
            repeatMode = RepeatMode.Restart
        ), label = "scrollOffset"
    )

    this
        .onSizeChanged { containerWidth = it.width }
        .graphicsLayer { translationX = scrollOffset }
}

使用方式:

var textLayoutResult by remember { mutableStateOf<TextLayoutResult?>(null) }

Text(
    text = "超长文本超长文本超长文本超长文本超长文本超长文本",
    modifier = Modifier
        .fillMaxWidth()
        .marquee(),
    maxLines = 1,
    onTextLayout = { textLayoutResult = it },
    overflow = TextOverflow.Clip
)

内容的提问来源于stack exchange,提问作者Jéluchu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:54:03