Quoi de plus vivant qu’une belle interface animée ? Les équipes design rivalisent d’ingéniosité pour permettre à l’utilisateur de mieux comprendre le fonctionnement d’une application, grâce, notamment, aux animations.
Mais le terme "animation" fait souvent peur aux développeur·se·s. Les keyframes, les interpolateurs, les translations… un charabia qui peut encourager l’équipe de dev à freiner et à limiter les designers sur leurs idées.
Et si on vous disait qu’implémenter des animations, c’est pas si difficile ?
Avec Compose, le "nouveau" framework UI de Google, c’est même plutôt simple quand on a assimilé les termes techniques. Vous ne les connaissez pas ? Pas de problème, on est là !
En partant d’une application certes mignonne mais plutôt statique, nous allons voir ensemble et en direct sur quels éléments jouer pour donner vie à vos écrans.
Notre objectif : que vous soyez à l’aise et que vous deveniez moteur dans la conception artistique du projet en proposant des animations simples et surtout peu coûteuses.
Pas besoin d’être un·e grand·e créatif·ve pour réaliser des applications chatoyantes !
13. • Use AnimatedVisibility(visible) to show/hide a
Composable
• Ability to customize enter / exit transitions
• Use AnimatedVisibilityScope with
Modifier.animateEnterExit(), you specify the child
element animation
Visibility
17. val animationSpec = tween<Color>(400)
val contentColor = animateColorAsState(
targetValue = if (isFav) {
MaterialTheme.colorScheme.onPrimary
} else {
MaterialTheme.colorScheme.onSurface
},
animationSpec = animationSpec
)
val containerColor = animateColorAsState(
targetValue = if (isFav) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.surface
},
animationSpec = animationSpec
)
Live coding results
18. Animate property from a State
• Use animate*AsState() APIs for value-based animation
• The animation is customizable with AnimationSpec
• Available animations:
animateDpAsState()
animateOffsetAsState()
animateFloatAsState()
animateColorAsState()
animateSizeAsState()
animateRectAsState()
animateIntAsState()
22. var atEnd by remember { mutableStateOf(false) }
val fabIcon =
AnimatedImageVector.animatedVectorResource(R.drawable.avd_anim)
Icon(
painter = rememberAnimatedVectorPainter(fabIcon, atEnd),
contentDescription = null
)
Live coding results
23. Animated Vector Drawable
• Bound to a state (boolean)
• AnimatedImageVector:
✓ AnimatedImageVector.animatedVectorResource
• Painter:
✓ rememberAnimatedVectorPainter(vector, state)
• To trigger the animation, just reverse the state:
✓ state = !state
28. • AnimatedNavHost replaces NavHost
• Same mechanism than XML enter/exit/popEnter/popExit
• Not yet into Compose AndroidX
✓ Use Accompanist library
• Missing : SharedElement between screens
Navigation transitions
32. Specifications, loops, transitions
AnimationSpecs allow to define how values should transform:
• tween: animates over the specified duration using an easing curve
• spring: a physics-based animation
• keyframes: based on the snapshot values specified at different timestamps
in the duration of the animation
• repeatable: repeat until it reaches the specified iteration count + a
animation (tween, spring, …)
• infiniteRepeatable: as repeatable, but indefinitely
• snap: immediately switches the value to the end value
38. LaunchedEffect
• LaunchedEffect is triggered during the composition
• The animation runs even if the Composable isn’t displayed on
screen
• Be careful with LazyLayout items
➢ LaunchedEffect is called each time the view is displayed
39. It's easy
Set the right animation,
at the right time
Pay attention to physics
ARO
Concernant les animated vector drawable, c’est un peu étrange mais ça reste dans la logique compose.
On doit avoir un état (eh oui encore) lié à l’animated Vector Drawable, récupérer la resource.
Préparer un painter qui va bien sur etre remembered entre les compositions et le passer en attribut d’une image.
Pour déclencher l’animation, on inversera simplement le booléen (au clic ou autre)