kwyntes
kwyntes

Reputation: 1302

Modifier.animateContentSize does not animate shrinking of content

This question describes the same problem as explained in this question, however since it did not provide any code I am opening a new one.

Using Modifier.animateContentSize(), I am able to animate the expansion of the content inside the card, however, as opposed to what as far as I know should be happening, I am unable to animate the reduction of the content.

Whenever I click the button after it has grown, instead of playing a shrinking animation, it just snaps back to its original size immediately, without any kind of transition.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TheThing() {
    var expanded by remember { mutableStateOf(false) }

    // A surface container using the 'background' color from the theme
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colorScheme.background
    ) {
        Column {
            Card(
                onClick = { expanded = !expanded },
                modifier = Modifier
                    .padding(16.dp)
                    .fillMaxWidth()
                    .animateContentSize()
            ) {
                Text("Clickable", style = MaterialTheme.typography.displayMedium)

                if (expanded) {
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                    Text("More text here... ")
                }
            }
        }
    }
}

Upvotes: 10

Views: 3103

Answers (2)

Andrei R
Andrei R

Reputation: 1986

I recommend you use AnimatedVisibility and animateContentSize combined.

  1. Remove animateContentSize from Card.
  2. Apply AnimatedVisibility and animateContentSize to expandable content:
AnimatedVisibility(visible = expanded) {
    Column(modifier = Modifier.animateContentSize()) {
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
        Text("More text here... ")
    }
}

Full code:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TheThing() {
    var expanded by remember { mutableStateOf(false) }

    // A surface container using the 'background' color from the theme
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colorScheme.background
    ) {
        Column {
            Card(
                onClick = { expanded = !expanded },
                modifier = Modifier
                    .padding(16.dp)
                    .fillMaxWidth()
            ) {
                Text("Clickable", style = MaterialTheme.typography.displayMedium)

                AnimatedVisibility(visible = expanded) {
                    Column(modifier = Modifier.animateContentSize()) {
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                        Text("More text here... ")
                    }
                }
            }
        }
    }
}

Result:

enter image description here

Upvotes: 5

riggaroo
riggaroo

Reputation: 2997

You should use AnimatedVisibility for the content that is inside the if statement. Whats happening here is that your if (expanded) statement is running immediately, so it makes your content disappear instantly, then the size changes do animate, but the content is already gone from the composition - making it look like the text is not animating away.

In the below example I'm customizing AnimatedVisibility to have a slower speed so you can see the actual animation happening. If you put a border around it you'll see the size animates too:

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun TheThing() {
    var expanded by remember { mutableStateOf(false) }

    // A surface container using the 'background' color from the theme
    Surface(
        modifier = Modifier.fillMaxSize(),

        ) {
        Column {
            Card(
                onClick = { expanded = !expanded },
                modifier = Modifier
                    .padding(16.dp)
                    .fillMaxWidth()
            ) {
                Column {
                    Text("Clickable")
                    AnimatedVisibility(
                        expanded, exit = fadeOut(animationSpec = tween(1000)) +
                                shrinkVertically(animationSpec = tween(1000))
                    ) {
                        Column {
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                            Text("More text here... ")
                        }
                    }
                }
            }
        }
    }
}

Upvotes: 0

Related Questions