animate*AsState

animate*AsState and AnimatedVisibility

animateFloatAsState(target) (and animateColorAsState, animateDpAsState and friends) returns a State that moves toward target whenever the target changes. AnimatedVisibility(visible) animates content in and out, here a fade plus an expand for the book's summary:

ui/BookScreens.kt: a button that grows when the book is in the cart (excerpt)Kotlin
  val scale by animateFloatAsState(if (inCart) 1.1f else 1f, tween(300), label = "scale")
  SideEffect { Log.d(TAG, "BookDetailScreen composed, inCart=$inCart") }
  ...
    Button(onClick = onToggleCart, Modifier.graphicsLayer {
      scaleX = scale; scaleY = scale                     // read in the draw phase only
      if (scale != 1f && scale != 1.1f) Log.d(TAG, "draw: scale %.3f".format(scale))
    }) {
  ...
    AnimatedVisibility(showSummary, enter = fadeIn() + expandVertically(),
      exit = fadeOut() + shrinkVertically()) {
      Text(book.summary, style = MaterialTheme.typography.bodyLarge)
    }

Tapping the button twice, to add the book and remove it again, logged:

Output of 127
09-25 02:58:17.860 18362 18362 D BookNestAnim: BookDetailScreen composed, inCart=true
09-25 02:58:20.007 18362 18362 D BookNestAnim: BookDetailScreen composed, inCart=false
09-25 02:58:20.068 18362 18362 D BookNestAnim: draw: scale 1.099
09-25 02:58:20.239 18362 18362 D BookNestAnim: draw: scale 1.012
09-25 02:58:20.274 18362 18362 D BookNestAnim: draw: scale 1.012

Two lessons are in those lines. First, the screen composed once per tap, not once per frame, because scale is read only inside the graphicsLayer lambda, which runs in the draw phase; reading it in the composable body would recompose the whole screen every frame. Second, animations are timed, not counted. On this heavily loaded emulator the first 300 ms animation drew no in-between frame at all and the second drew three, 170 ms apart, yet both ended on time at their targets. tween gives a duration and easing; spring, the default, gives physics and handles a target that changes mid-flight.