kotlinandroid-jetpack-composejetpack-compose-animation

How to animate all of the placements of my Jetpack Compose Row due to visibility changes of just one element?


I'm trying to put together an effect that looks something like iOS's in place table editing. When in "edit mode" selection controls slide in on one side of each row. I did this using a simple AnimatedVisibility on my selection button and tweaking the enter/exit parameters. The button itself looks nice, but the other elements of my row don't also animate their placement. They just snap update at the end? How should I go about getting this "selection button slides in AND the other widgets bunch up a little to make room for" effect as I go in and out of the "edit mode"?

The code I'm currently using for the rows looks like:

Row(
    modifier = Modifier
        .fillMaxWidth()
        .padding(vertical = 10.dp),
    verticalAlignment = Alignment.CenterVertically
) {
    Icon( ... )
    Spacer(modifier = Modifier.width(4.dp))
    Text(text = keyInfo.name, modifier = Modifier.weight(1.0f), maxLines = 1)
    Spacer(modifier = Modifier.width(10.dp))
    SettingsLabel(text = keyInfo.created.shortPrinted())
    AnimatedVisibility(visible = allowSelection,
        enter = slideInHorizontally(initialOffsetX = { w -> w }),
        exit = slideOutHorizontally(targetOffsetX = { w -> w })
    ) {
        IconButton(
            onClick = onSelectionClick, modifier = Modifier
                .padding(start = 16.dp)
                .size(28.dp)
        ) {
            when (isSelected) {
                true -> Icon(
                    Icons.Outlined.CheckCircle, "${keyInfo.name} selected for edit"
                )
                false -> Icon(
                    Icons.Default.RadioButtonUnchecked, "${keyInfo.name} not selected for edit"
                )
            }
        }
    }
}

Solution

  • You can combine Enter/ExitTransitions with the + sign. Combining slideInHorizontally with expandHorizontally, and slideOutHorizontally with shrinkHorizontally will give you the result you want. You may want to tweak the speed and values to match exactly what you need.

    AnimatedVisibility(visible = allowSelection,
        enter = slideInHorizontally(initialOffsetX = { w -> w }) + expandHorizontally(expandFrom = Alignment.End),
        exit = slideOutHorizontally(targetOffsetX = { w -> w }) + shrinkHorizontally(shrinkTowards = Alignment.End)
    )
    

    enter image description here