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

Android Compose:如何在文本行末尾正确定位动画组件

问题:Jetpack Compose 如何在文本行末尾定位动画组件

我想在文本行的末尾添加动画,目前没法给部分文本直接加动画,所以自己想了个方案:先放置一段文本,再根据文本最后一行的末尾位置来设置动画的位置。现在已经写出了部分代码,但不知道怎么设置动画的偏移量,让它能紧跟在文本最后一行的末尾(效果类似:动画组件和文本最后一行在同一行,紧贴文本右侧)。

我的现有代码:

var animationWidthState by remember { mutableIntStateOf(0) }
val animationWidth by remember { derivedStateOf { animationWidthState } }
// 这里需要替换为正确的坐标
var animationOffset: Offset? by remember { mutableStateOf(null) }


Box(
    modifier = modifier.padding(start = 16.dp),
) {
    Text(
        text = "Some long text that will",
        onTextLayout = { textLayoutResult ->
            if (textLayoutResult.lineCount > 0) {
                val lastLineIndex = textLayoutResult.lineCount - 1
                // 获取最后一行的右侧x坐标(像素)
                val lastLineRight = textLayoutResult.getLineRight(lastLineIndex)
                // 获取最后一行的顶部y坐标(像素)
                val lastLineTop = textLayoutResult.getLineTop(lastLineIndex)
                
                val size = textLayoutResult.size.width
                val willAnimationFit = size - lastLineRight > animationWidth
                if (willAnimationFit) {
                    with(density) {
                        // 保存偏移量:水平是最后一行右侧,垂直是行顶部位置
                        animationOffset = Offset(
                            x = lastLineRight.toDp(),
                            y = lastLineTop.toDp()
                        )
                    }
                }
            }
        }
    )
                  
    AnimatedContent(
        modifier = animationOffset?.let { offset ->
            Modifier.offset(offset.x, offset.y)
        } ?: Modifier,
        targetState = state.value,
        transitionSpec = {
            slideAnimation(
                slideOutTravelInPx = slideOutTravelInPx,
                slideInTravelInPx = slideInTravelInPx,
            )
        },
    ) { targetState ->
          Box(
              modifier = Modifier.onGloballyPositioned {
                  animationWidthState = it.size.width
              },
          ) {
                Text(
                    text = stringResource(id = targetState.textRes),
                    color = Color.black,
                )
            }
      }
}

关键修改点:

  • 把原来的单一位置变量改成animationOffset,同时保存水平和垂直偏移量
  • 在onTextLayout中:
    • 用getLineRight获取最后一行的右侧x坐标,作为动画组件的水平偏移起点
    • 用getLineTop获取最后一行的顶部y坐标,保证动画组件和文本行顶部对齐
  • 直接将计算好的偏移量应用到AnimatedContent的offset修饰符上

进阶优化(基线对齐)

如果要让动画文本和原文本的基线完全对齐(避免上下错位),可以在动画内部的Text中获取基线并调整偏移:

// 先在外部保存原文本的基线
var lastLineBaseline by remember { mutableIntStateOf(0) }

// 原Text的onTextLayout中添加
lastLineBaseline = textLayoutResult.getLineBaseline(lastLineIndex)

// AnimatedContent内部的Text修改
Text(
    text = stringResource(id = targetState.textRes),
    color = Color.black,
    onTextLayout = { animTextLayout ->
        val animBaseline = animTextLayout.getLineBaseline(0)
        animationOffset?.let { originalOffset ->
            with(density) {
                // 原文本基线 - 动画文本基线 = 修正后的y偏移
                val adjustedY = originalOffset.y - animBaseline.toDp() + lastLineBaseline.toDp()
                animationOffset = originalOffset.copy(y = adjustedY)
            }
        }
    }
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:57:40