diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/Background.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/Background.kt index 0d02baac7..cc797409f 100644 --- a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/Background.kt +++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/Background.kt @@ -17,13 +17,18 @@ package com.google.samples.apps.nowinandroid.core.ui.component import android.content.res.Configuration -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size +import androidx.compose.material3.LocalAbsoluteTonalElevation import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview @@ -31,10 +36,11 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.google.samples.apps.nowinandroid.core.ui.theme.LocalBackgroundTheme import com.google.samples.apps.nowinandroid.core.ui.theme.NiaTheme +import kotlin.math.tan /** * The main background for the app. - * Uses [LocalBackgroundTheme] to set the color and tonal elevation of a [Surface]. + * Uses [LocalBackgroundTheme] to set the color and tonal elevation of a [Box]. * * @param modifier Modifier to be applied to the background. * @param content The background content. @@ -50,13 +56,16 @@ fun NiaBackground( color = if (color == Color.Unspecified) Color.Transparent else color, tonalElevation = if (tonalElevation == Dp.Unspecified) 0.dp else tonalElevation, modifier = modifier.fillMaxSize(), - content = content - ) + ) { + CompositionLocalProvider(LocalAbsoluteTonalElevation provides 0.dp) { + content() + } + } } /** - * A gradient background for select screens, to be overlaid on top of [NiaBackground]. - * Uses [LocalBackgroundTheme] to set the gradient colors of a [Box]. + * A gradient background for select screens. Uses [LocalBackgroundTheme] to set the gradient colors + * of a [Box]. * * @param modifier Modifier to be applied to the background. * @param topColor The top gradient color to be rendered. @@ -70,21 +79,56 @@ fun NiaGradientBackground( bottomColor: Color = LocalBackgroundTheme.current.secondaryGradientColor, content: @Composable () -> Unit ) { - val gradientModifier = Modifier.background( - Brush.verticalGradient( - listOf( - if (topColor == Color.Unspecified) Color.Transparent else topColor, - Color.Transparent, - if (bottomColor == Color.Unspecified) Color.Transparent else bottomColor - ) - ) - ) - Box( - modifier = modifier - .fillMaxSize() - .then(gradientModifier) - ) { - content() + val currentTopColor by rememberUpdatedState(topColor) + val currentBottomColor by rememberUpdatedState(bottomColor) + NiaBackground(modifier) { + Box( + Modifier + .fillMaxSize() + .drawWithCache { + // Compute the start and end coordinates such that the gradients are angled 11.06 + // degrees off the vertical axis + val offset = size.height * tan( + Math + .toRadians(11.06) + .toFloat() + ) + + val start = Offset(size.width / 2 + offset / 2, 0f) + val end = Offset(size.width / 2 - offset / 2, size.height) + + // Create the top gradient that fades out after the halfway point vertically + val topGradient = Brush.linearGradient( + 0f to if (currentTopColor == Color.Unspecified) { + Color.Transparent + } else { + currentTopColor + }, + 0.724f to Color.Transparent, + start = start, + end = end, + ) + // Create the bottom gradient that fades in before the halfway point vertically + val bottomGradient = Brush.linearGradient( + 0.2552f to Color.Transparent, + 1f to if (currentBottomColor == Color.Unspecified) { + Color.Transparent + } else { + currentBottomColor + }, + start = start, + end = end, + ) + + onDrawBehind { + // There is overlap here, so order is important + drawRect(topGradient) + drawRect(bottomGradient) + } + } + ) { + content() + } } }