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
相关产品推荐
相关产品推荐

