如何在 Jetpack Compose 中实现平移+缩放动画?

How to implement a translate + scale animation in Jetpack Compose?

我有一个屏幕,屏幕的一角有一个图像,我想将它设置为动画到屏幕中央。 有点像从

Icon(
    painter = //,
    contentDescription = //,
    modifier = Modifier.size(36.dp)
)

Icon(
    painter = //,
    contentDescription = //,
    modifier = Modifier.fillMaxSize()
)

第一个放在屏幕的左上角,第二个在中间。如何在两种状态之间设置动画?

要使动画在 Compose 中工作,您需要为某个特定修饰符的值设置动画。无法在不同的修改器集之间设置动画。

this 文档段落之后,您可以为 Modifier.size 设置动画值。

首先我等待确定图像的大小,使用这个值可以设置 size 修饰符(我使用 then 之前有一个空的 Modifier)然后可以对这个值进行动画处理。

这是一个示例:

Column {
    val animatableSize = remember { Animatable(Size.Zero, Size.VectorConverter) }
    val (containerSize, setContainerSize) = remember { mutableStateOf<Size?>(null) }
    val (imageSize, setImageSize) = remember { mutableStateOf<Size?>(null) }
    val density = LocalDensity.current
    val scope = rememberCoroutineScope()
    Button(onClick = {
        scope.launch {
            if (imageSize == null || containerSize == null) return@launch
            val targetSize = if (animatableSize.value == imageSize) containerSize else imageSize
            animatableSize.animateTo(
                targetSize,
                animationSpec = tween(durationMillis = 1000)
            )
        }
    }) {
        Text("Animate")
    }
    Box(
        Modifier
            .padding(20.dp)
            .size(300.dp)
            .background(Color.LightGray)
            .onSizeChanged { size ->
                setContainerSize(size.toSize())
            }
    ) {
        Image(
            Icons.Default.Person,
            contentDescription = null,
            modifier = Modifier
                .then(
                    if (animatableSize.value != Size.Zero) {
                        animatableSize.value.run {
                            Modifier.size(
                                width = with(density) { width.toDp() },
                                height = with(density) { height.toDp() },
                            )
                        }
                    } else {
                        Modifier
                    }
                )
                .onSizeChanged { intSize ->
                    if (imageSize != null) return@onSizeChanged
                    val size = intSize.toSize()
                    setImageSize(size)
                    scope.launch {
                        animatableSize.snapTo(size)
                    }
                }
        )
    }
}

结果:

试试这个:

@Composable
fun DUM_E_MARK_II(triggered: Boolean) {
    BoxWithConstraints {
        val size by animateDpAsState(if (triggered) 36.dp else maxHeight)
        Icon(
            imageVector = Icons.Filled.Warning,
            contentDescription = "Just a better solution to the problem",
            modifier = Modifier.size(size)
        )
    }
}