如何在Jetpack Compose中实现可自定义起止位置的平移动画
Jetpack Compose 自定义起止位置平移动画实现方案
Compose 官方动画库原生支持自定义起止位置的平移动画,核心通过偏移量的数值动画配合offset修饰符实现,以下是两种常用场景的实现方案:
1. 状态触发式平移动画(简单场景)
适合点击、状态切换触发的一次性平移动画,使用animateDpAsState实现,直接修改起止偏移变量即可自定义位置:
@Composable fun BasicTranslationDemo() { // 动画触发状态 var moveToEnd by remember { mutableStateOf(false) } // 自定义起止位置,单位为dp,可按需调整数值 val startOffsetX = 0.dp val endOffsetX = 200.dp val startOffsetY = 0.dp val endOffsetY = 120.dp // X、Y轴偏移动画 val animatedX by animateDpAsState( targetValue = if (moveToEnd) endOffsetX else startOffsetX, animationSpec = tween(durationMillis = 1000) // 可自定义动画时长、插值器 ) val animatedY by animateDpAsState( targetValue = if (moveToEnd) endOffsetY else startOffsetY, animationSpec = tween(durationMillis = 1000) ) Column(Modifier.padding(16.dp)) { Button(onClick = { moveToEnd = !moveToEnd }) { Text("切换平移动画") } Box( Modifier .padding(top = 20.dp) .size(50.dp) .background(Color.Blue) .offset(x = animatedX, y = animatedY) ) } }
2. 可精细化控制的平移动画
适合需要手动控制动画进度、暂停/倒放、动态修改起止位置的场景,使用Animatable实现:
@Composable fun ControlledTranslationDemo() { // 自定义起止偏移,可动态修改 val startX = 0.dp val endX = 300.dp val startY = 0.dp val endY = 200.dp val animatableX = remember { Animatable(startX, Dp.VectorConverter) } val animatableY = remember { Animatable(startY, Dp.VectorConverter) } val coroutineScope = rememberCoroutineScope() Column(Modifier.padding(16.dp)) { Button(onClick = { coroutineScope.launch { // 同步启动X、Y轴动画,移动到结束位置 launch { animatableX.animateTo(endX, tween(1500)) } launch { animatableY.animateTo(endY, tween(1500)) } } }) { Text("移动到结束位置") } Button( onClick = { coroutineScope.launch { launch { animatableX.animateTo(startX) } launch { animatableY.animateTo(startY) } } }, Modifier.padding(top = 8.dp) ) { Text("回到起始位置") } Box( Modifier .padding(top = 20.dp) .size(60.dp) .background(Color.Red) .offset(x = animatableX.value, y = animatableY.value) ) } }
注意:
offset修饰符仅改变组件的绘制位置,不会影响其在布局树中的占位,如果需要偏移同时影响布局占位,可以替换为absoluteOffset,或配合layout修饰符实现。如果需要使用像素作为偏移单位,把Dp类型替换为Float,offset修饰符改用offset { IntOffset(animatedX.roundToInt(), animatedY.roundToInt()) }即可。
内容的提问来源于stack exchange,提问作者Ali Jawad Hussain Gorayya
相关产品推荐
相关产品推荐

