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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:36:09