androidandroid-jetpack-composematerial-designandroid-elevation

Two adjacent Composables with the same elevation present a dividing shadow


I'm wanting to present a collapsible bar below a sticky top bar. In the initial state when the collapsible bar is fully expanded, I want both bars to look like they are on the exact same elevation. Then, when the collapsible bar collapses on scroll, the sticky bar should elevate up and the collapsible bar should look as if it's sliding underneath the sticky top bar.

The issue I'm seeing is in the initial state, there's a light dividing shadow between the two bars in dark mode even though they have the exact same elevation value.

Sticky top app bar, divider, collapsible top app bar

Relevant code (left out the scroll logic for brevity):

Column(modifier = Modifier.fillMaxWidth()) {
    TopAppBar(
        navigationIcon = {
            IconButton()
        },
        title = {
            Text(text = "Sticky top app bar")
        },
        elevation = 4.dp,
    )
    Surface(
        modifier = Modifier.fillMaxWidth(),
        elevation = 4.dp,
    ) {
        Text(text = "Collapsible top app bar")
    }
}

Anyone familiar with how to avoid that dividing shadow between the two bars?


Solution

  • I ended up adding material3 to my project, updating to androidx.compose.material3.Surfaces, setting the initial shadowElevation of the sticky top bar to 0.dp, and then gradually animating shadowElevation based on the collapsing top bar scroll progress.

    val maxElevation = 3.dp
    Surface(
        modifier = modifier.graphicsLayer {
            shadowElevation = lerp(0.dp.toPx(), maxElevation.toPx(), collapsingStateProgress.value)
        },
        shadowElevation = if (header == null) maxElevation else 0.dp,
        tonalElevation = maxElevation,
    )