Search code examples
androidkotlinandroid-jetpack-composeandroid-jetpack-compose-animation

How to animate as size in jetpack compose


I want to make a size of Column to be 0.dp after all my animation done. I am trying to shrink my Column to 0.dp after all children hide. I tried below of this code

@Preview(showBackground = true)
@Composable
fun MoveText() {
    var columnHeightPx by remember {
        mutableStateOf(0f)
    }
    var visible by remember { mutableStateOf(true) }
    val iconOffsetAnimation: Dp by animateDpAsState(
        if (visible) 13.dp else 0.dp,
        tween(1000)
    )
    val textOffsetAnimation: Dp by animateDpAsState(
        if (visible) 6.dp else 0.dp,
        tween(1000)
    )
    val viewAlpha: Float by animateFloatAsState(
        targetValue = if (visible) 1f else 0f,
        animationSpec = tween(
            durationMillis = 1000,
        )
    )
    ScrollComposeTheme {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 16.dp, top = 16.dp)
        ) {
            Column(
                modifier = Modifier
                    .onGloballyPositioned { coordinates ->
                        columnHeightPx = coordinates.size.height.toFloat()
                    }
                    .background(Color.LightGray)
            ) {
                Image(
                    modifier = Modifier
                        .padding(top = iconOffsetAnimation),
                    alpha = viewAlpha,
                    imageVector = Icons.Default.ShoppingCart,
                    contentDescription = null,
                )
                Text(
                    modifier = Modifier
                        .padding(top = textOffsetAnimation),
                    text = "Hello, Anna",
                    fontSize = 20.sp,
                    color = Color.Black.copy(alpha = viewAlpha),
                )
            }
            Button(
                modifier = Modifier
                    .padding(top = 10.dp),
                onClick = {
                    visible = !visible
                },
            ) {
                Text(text = "Move Text")
            }
        }
    }
}

It looks like this when animation completed :(

enter image description here

I am trying to shrink my size like this video. In this video, I only want to shrink the Icon & Text with Column, but I am getting the above image problem. I tried to search in stack overflow and I found to use animateSizeAsState, but I am not sure it'll work or not because it gives error

val heightInDp = animateSizeAsState(
        targetValue = if (visible) columnHeightPx else 0,
        animationSpec = tween(
            durationMillis = 1000,
        )
    )

Error on targetValue

Type mismatch.
 Required:  Size
 Found: { Comparable  & Number }

Solution

  • animateSizeAsState returns as State<Size> object,

    Size contains width and height parameters in pixel in Float unit but what you need is height is in dp. You can convert pixel to dp or dp to pixel using Density.

    val density = LocalDensity.current
    val heightInDp = animateDpAsState(
        targetValue = if (visible) with(density){columnHeightPx.toDp()} else 0.dp,
        animationSpec = tween(
            durationMillis = 1000,
        )
    )