Compose edge-to-edge animation

Denis Vlasov
2 min readOct 27, 2022

The edge-to-edge app can stand above compared to other apps. Google has the official documentation for this feature. You can easily configure this feature in your app.

After reading you will learn how to draw behind status and navigation bars. I show examples with a list and animations.

This guide use Jetpack Compose. The Jetpack Compose is Android’s recommended, modern toolkit for building native UI.

Let’s create a simple project with a list of text. This project contains a button, touch the button move circle and start the reveal animation. I want to show this animation behind system bars (status & navigation bars).

Let’s take a look in more detail.

Firstly, setup the app theme in themes.xml

<style name="Theme.EdgeToEdgeCompose" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
</style>

Use this theme in the android manifest. Carefully use this theme in compose activity code, because it rewrites the status bar color to primary color. I use MaterialTheme instead.

The next line is necessary for drawing behind system bars. Add it to your activity class MainActivity.kt.

WindowCompat.setDecorFitsSystemWindows(window, false)

Okay, the setup is done. Let’s make some animations. You can find animation documentation on Android developer.

I use updateTransition to move and reveal the circle and AnimatedVisibility to the android logo appears with fade. I like these animations because you can see them in Android Studio without a device.

Setup updateTransition animation. CircleState contains 3 states: start, center, expanded.

@Composable
private fun updateTransitionData(
circleState: CircleState, circleSize: Dp, circlePadding: Dp, updateState: (CircleState) -> Unit
): TransitionData {
val halfScreen = LocalConfiguration.current.screenWidthDp / 2
val transition = updateTransition(circleState, label = "circle anim")
val moveToCenterAnim = transition.animateDp(label = "move to center",
transitionSpec = { spring(dampingRatio = DampingRatioMediumBouncy) }) { state ->
when (state) {
Start -> 0.dp
Center
, Expanded -> (halfScreen).dp - circleSize + circlePadding
}
}
val expandToFullscreenAnim = transition.animateFloat(label = "expand to fullscreen",
transitionSpec = { tween(easing = EaseIn) }) { state ->
when (state) {
Start, Center -> 1f
Expanded -> 24f
}
}
if (transition.currentState == Center && transition.targetState == Center) {
updateState(Expanded)
}
return remember(transition) { TransitionData(moveToCenterAnim, expandToFullscreenAnim) }
}

Setup AnimatedVisibility animation. Just simple fade animation.

AnimatedVisibility(
visible = clickedStartAnim, enter = fadeIn(
animationSpec = tween(delayMillis = 150, easing = EaseIn)
)
)

The result is on the gif:

example of reveal animation

Code sample available on Github:

https://github.com/VDenis/EdgeToEdgeCompose

--

--