Status Update
Comments
al...@gmail.com <al...@gmail.com> #2
I think this might not be too difficult to support if you create an ambient that holds the current 'parent elevation'. I wrote my own example surface implementation illustrating this:
@Composable
fun CoreUiSurface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
backgroundColor: Color = CoreUiTheme.colors.surfacePrimary,
contentColor: Color = CoreUiTheme.colors.textPrimary,
border: BorderStroke? = null,
elevation: Dp = 0.dp,
content: @Composable () -> Unit,
) {
val parentElevation = AmbientParentElevation.current
val absoluteElevation = parentElevation + elevation
Box(
modifier = modifier
.drawShadow(elevation = elevation, shape = shape, clip = false)
.zIndex(elevation.value)
.then(if (border == null) Modifier else Modifier.border(border, shape))
.background(color = backgroundColor.getElevatedBackgroundColor(absoluteElevation), shape = shape)
.clip(shape)
) {
ProvideParentElevation(absoluteElevation) {
ProvideContentColor(color = contentColor, children = content)
}
}
}
@Composable
private fun Color.getElevatedBackgroundColor(elevation: Dp): Color {
if (elevation == 0.dp) return this
if (!CoreUiTheme.colors.isDarkMode) return this
if (this != CoreUiTheme.colors.surfacePrimary) return this
val overlayAlpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
return CoreUiTheme.colors.blue90.copy(alpha = overlayAlpha).compositeOver(this)
}
internal val AmbientParentElevation = staticAmbientOf { 0.dp }
@Composable
internal fun ProvideParentElevation(parentElevation: Dp, children: @Composable () -> Unit) {
Providers(AmbientParentElevation provides parentElevation, children = children)
}
cl...@google.com <cl...@google.com>
an...@google.com <an...@google.com>
lp...@google.com <lp...@google.com> #3
Yep, your implementation seems reasonable / how we would implement this. There are some questions around whether this behavior is easy to understand / expected, but at least for the migration case it seems reasonable to support in some capacity.
al...@gmail.com <al...@gmail.com> #4
I'll leave it up to your team to decide, but IMO (regardless of whether the behavior is easy to understand/expected), this behavior definitely has its benefits. One example where we depend on it in our own app is when placing surface-background-colored components on top of bottom-sheets. Without the concept of absolute elevation, those components end up looking like dark punch-out holes against a much brighter bottom sheet background in dark mode.
Just wanted to share my experience. :)
ch...@google.com <ch...@google.com> #5
Thanks to Louis for pointing me towards AmbientElevationOverlay
and ElevationProvider
as a way to make this a bit easier to implement.
ap...@google.com <ap...@google.com> #6
Branch: androidx-master-dev
commit a632fa2b38d798a4350214875b4e3695ebc0d0b6
Author: Louis Pullen-Freilich <lpf@google.com>
Date: Thu Oct 22 16:44:07 2020
Adds AmbientAbsoluteElevation to represent the sum of elevation provided by Surfaces. Also changes Surface to use this absolute elevation when calculating elevation overlays, to represent the total elevation at that point in the hierarchy, and not the elevation of the nearest Surface.
Bug:
Test: ElevationOverlayTest, SurfaceTest
Relnote: "Surface now uses the absolute (total) elevation when calculating elevation overlays, so a Surface nested in another Surface will use the combined elevation to draw the overlay."
Change-Id: I7bd2b08da276d5624baad6a2e59eb74bc021bc45
M compose/material/material/api/current.txt
M compose/material/material/api/public_plus_experimental_current.txt
M compose/material/material/api/restricted_current.txt
A compose/material/material/samples/src/main/java/androidx/compose/material/samples/ElevationSamples.kt
M compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ElevationOverlayTest.kt
M compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SurfaceTest.kt
M compose/material/material/src/commonMain/kotlin/androidx/compose/material/Elevation.kt
M compose/material/material/src/commonMain/kotlin/androidx/compose/material/Surface.kt
lp...@google.com <lp...@google.com>
al...@gmail.com <al...@gmail.com> #7
Woot thanks Louis!
Description
Inhttps://github.com/material-components/material-components-android/blob/89a1bf883fa614702bb43d2cfa75a38005a42421/lib/java/com/google/android/material/internal/ViewUtils.java#L259-L271
material-components-android
, views automatically inherit the elevation of their parentViewGroup
s using this utility method:For example, say you have a
MaterialButton
(with 4dp elevation) contained inside of aBottomSheet
(with 16dp elevation). In dark theme, theMaterialButton
will inherit theBottomSheet
's elevation, meaning that its elevation overlay will render as if theMaterialButton
had 20dp elevation instead of 4dp elevation.It would be useful if there was a builtin mechanism to support this in Compose. This would make it easier to migrate UIs written with material-components-android to Compose while still maintaining UI consistency.