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

Arp*_*kla 3 android kotlin android-jetpack-compose jetpack-compose-animation

我有一个屏幕,屏幕的一角有一个图像,我想将其动画到屏幕的中心。类似从

Icon(
    painter = //,
    contentDescription = //,
    modifier = Modifier.size(36.dp)
)
Run Code Online (Sandbox Code Playgroud)

Icon(
    painter = //,
    contentDescription = //,
    modifier = Modifier.fillMaxSize()
)
Run Code Online (Sandbox Code Playgroud)

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

Phi*_*hov 7

要使动画在 Compose 中工作,您需要对某些特定修改器的值进行动画处理。您无法在不同的修改器集之间设置动画。

按照文档段落,您可以为 的值设置动画Modifier.size

首先,我等待确定图像的大小,使用该值size可以设置修改器(我之前使用thenModifier),然后可以对该值进行动画处理。

这是一个示例:

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)
                    }
                }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:


Ric*_*per 7

试试这个:

@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)
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 那么,是什么让您认为这不是正确的解决方案?与标记的答案相比,它更有效。 (3认同)