androidkotlinandroid-jetpack-composeandroid-jetpackjetpack-compose-animation

Animation with increasing sizes in Jetpack Compose


I want to make an animation of a button, when clicked, its sizes increase and go beyond the size of the Box(). I wrote an animation with a custom Shape, it works, but where it is used, you have to write Modifier.size(21.dp) instead of Modifier.size(20.dp). And look like:

1dp as a space for animation

Can I somehow write an animation with an output beyond the sizes of Box()? Because now the solution looks a little complicated


Solution

  • Default Composables like Box, Row or Column limit maximum height or width a child can get based on their maximum Constraints. You can find more details about Constraints and how size modifiers work under the hood in this answer.

    What you should do is to force maximum Constraints beyond parent if you wish to increase a child's maximum dimensions bigger than parent.

    You can use Modifier.wrapContentSize(unBounded=true), Modifier.requiredSize or Modifier.layout{} which wrapContentSize also does under the hood to animate size beyond parents.

    @Preview
    @Composable
    private fun Test() {
    
        var target by remember {
            mutableStateOf(20.dp)
        }
        val size by animateDpAsState(target)
    
        Column(
            modifier = Modifier.fillMaxSize().padding(20.dp)
        ) {
    
            Button(
                onClick = {
                    target = if (size == 20.dp) {
                        40.dp
                    } else {
                        20.dp
                    }
                }
            ) {
                Text("Current size $size")
            }
    
            Spacer(modifier = Modifier.height(20.dp))
            Box(modifier = Modifier.size(20.dp).border(1.dp, Color.Red)) {
    
                Box(
                    modifier = Modifier
                        .size(size)
                        .background(Color.Blue)
                )
            }
    
            Spacer(modifier = Modifier.height(20.dp))
            Box(modifier = Modifier.size(20.dp).border(1.dp, Color.Red)) {
                Box(
                    modifier = Modifier
                        // This will let child to get Constraints.Infinity for maxWidth and Height
                        // so it can be measured with next Size modifier's max bounds
                        .wrapContentSize(unbounded = true)
                        .size(size)
                        .background(Color.Green)
                )
            }
    
            Spacer(modifier = Modifier.height(20.dp))
            Box(modifier = Modifier.size(20.dp).border(1.dp, Color.Red)) {
                Box(
                    modifier = Modifier
                        // This will let child to set max width and height as they choose
                        .requiredSize(size)
                        .background(Color.Magenta)
                )
            }
        }
    }