Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jetpack Compose Animations

Jetpack Compose Animations

Walkthrough of the animation APIs in Jetpack Compose and examples of how they are implemented.

Erik Manberger

March 26, 2023
Tweet

Other Decks in Programming

Transcript

  1. Why use animations? • Add visual cues to notify what’s

    going on in your app • When UI changes state • Higher quality look and feel
  2. Jetpack Compose Animations • High-level animation APIs • Many APIs

    available as Composable functions • Backed by lower-level APIs built with Kotlin coroutine suspend functions
  3. AnimatedVisibility • Animates appearance/disappearance of content • Visible parameter •

    Customise with EnterTransition/ExitTransition • Fade, Expand/Shrink, Scale, Slide

  4. AnimatedVisibility @Composable fun AnimatedVisibility( visible: Boolean, modifier: Modifier = Modifier,

    enter: EnterTransition = fadeIn() + expandIn(), exit: ExitTransition = shrinkOut() + fadeOut(), label: String = "AnimatedVisibility", content: @Composable() AnimatedVisibilityScope.() -> Unit ) { val transition = updateTransition(visible, label) AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content) }
  5. AnimatedVisibility @Composable fun ToggleGreeting() { var visible by remember {

    mutableStateOf(false) } Button(onClick = { visible = !visible }) { Text(text = "Greetings") } if (visible) { Text(text = "Hello Android!!") } }
  6. AnimatedVisibility @Composable fun ToggleGreeting() { var visible by remember {

    mutableStateOf(false) } Button(onClick = { visible = !visible }) { Text(text = "Greetings") } AnimatedVisibility (visible) { Text(text = "Hello Android!!") } }
  7. AnimatedContent • A container that animates content automatically • targetState

    • ContentTransform • transistionSpec to customise
  8. AnimatedContent @Composable fun <S> AnimatedContent( targetState: S, modifier: Modifier =

    Modifier, transitionSpec: AnimatedContentScope<S>.() -> ContentTransform contentAlignment: Alignment, content: @Composable() AnimatedVisibilityScope.(targetState: S) -> Unit ) class ContentTransform( val targetContentEnter: EnterTransition, val initialContentExit: ExitTransition, targetContentZIndex: Float = 0f, sizeTransform: SizeTransform? = SizeTransform() )
  9. AnimatedContent @Composable fun AnimatedCount() { Column { var count by

    remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text("Add") } AnimatedContent(targetState = count) { targetCount -> Text(text = "Count: $targetCount") } } }
  10. CrossFade • Switch between two layouts • When targetState is

    changed animation is triggered • FiniteAnimationSpec con fi gures animation
  11. CrossFade @Composable fun <T> Crossfade( targetState: T, modifier: Modifier =

    Modifier, animationSpec: FiniteAnimationSpec<Float> = tween(), label: String = "Crossfade", content: @Composable (T) -> Unit ) { val transition = updateTransition(targetState, label) transition.Crossfade(modifier, animationSpec, content = content) }
  12. CrossFade var isGreen by remember { mutableStateOf(false) } Crossfade(targetState =

    isGreen) { target -> when (target) { true -> Text("CrossFade", color = Color.Green) else -> Text("CrossFade") } }
  13. animateContentSize • Animates its own size when child modi fi

    er/Composable changes size • FiniteAnimationSpec can specify animation • A fi nishedListener can notify when size animation is done
  14. animateContentSize @Composable fun AnimateContentSize() { var showAll by remember {

    mutableStateOf(false) } val maxLines = if (showAll) Int.MAX_VALUE else 1 Column(modifier = Modifier.animateContentSize()) { Button() Text(maxLines = maxLines) } }
  15. animateValueAsState • Easiest animation API for animating single value •

    Provide target value animates to that from current value • Customise with AnimationSpec • Float, Color, Dp, Size, O ff set, Rect, Int, IntO ff set and IntSize
  16. animateValueAsState @Composable fun <T, V : AnimationVector> animateValueAsState( targetValue: T,

    typeConverter: TwoWayConverter<T, V>, animationSpec: AnimationSpec<T> = remember { spring() }, visibilityThreshold: T? = null, label: String = "ValueAnimation", finishedListener: ((T) -> Unit)? = null ): State<T>
  17. animateValueAsState val size by animateDpAsState( targetValue = if (isExpanded) 160.dp

    else 80.dp ) Box( modifier = Modifier .size(size) .background(Color.Green) )
  18. updateTransition • Creates and remembers an instance of Transition •

    Transition manages 1+ animations runs simultaneously between states • Use animateValue for child animations • Use enum type to ensure type safety • Used in AnimatedVisibility, AnimatedContent, CrossFade
  19. @Composable fun <T> updateTransition( targetState: T, label: String? = null

    ): Transition<T> { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { onDispose { transition.onTransitionEnd() } } return transition } updateTransition
  20. var currentShape by remember { mutableStateOf(Shape.Rectangle) } val transition =

    updateTransition(targetState = currentShape) val cornerRadius by transition.animateDp { targetShape -> when (shape) { Shape.Rectangle -> 0.dp Shape.Circle -> size/2 } } val color by transition.animateColor { targetShape -> when (shape) { Shape.Rectangle -> Color.Green Shape.Circle -> Color.Red } } Box(modifier = Modifier .size(size) .clip(RoundedCornerShape(cornerRadius)) .background(color) ) updateTransition
  21. rememberInfiniteTransition • Creates an instance of In fi niteTransition •

    Animations start immediately & don’t stop • Set AnimationSpec with in fi niteRepeatable • Child animations: animateColor, animateFloat, …, animateValue
  22. @Composable fun rememberInfiniteTransition(): InfiniteTransition { val infiniteTransition = remember {

    InfiniteTransition() } infiniteTransition.run() return infiniteTransition } rememberInfiniteTransition
  23. @Composable fun RememberInfiniteTransition() { val infiniteTransition = rememberInfiniteTransition() val degree

    by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 45f, animationSpec = infiniteRepeatable( animation = tween(500), repeatMode = RepeatMode.Reverse ) ) Canvas(modifier = Modifier.size(160.dp), onDraw = { drawArc( color = Color.Yellow, startAngle = degree, sweepAngle = 360f - 2*degree, useCenter = true ) }) } rememberInfiniteTransition
  24. Animatable • Coroutine-based API for animating a single value •

    Animates value when changed via animateTo • Ongoing animation will be cancelled when new animation is started • Float, Color • Used in animateValueAsState
  25. Animation • Animation calculation engine that higher-level APIs use •

    Use to manually control animation time • TargetBasedAnimation, DecayAnimation
  26. AnimationSpec • spring(dampingRatio, sti ff ness) • tween(durationMillis, delayMillis, easing)

    • keyframes(durationMillis, ranges, easing) • repeatable(iterations, animation, repeatMode) • in fi niteRepeatable(animation, repeatMode) • snap(delayMillis)
  27. Summary • High-level APIs, easy to use • Start out

    with AnimatedVisibility and animateContentSize • https://developer.android.com/jetpack/compose/animation