sample the bar colour from the gradient, saturate the accents

This commit is contained in:
austinried
2026-10-04 00:29:53 +00:00
parent 139e12af75
commit 121d793b72
2 changed files with 34 additions and 26 deletions
@@ -78,6 +78,7 @@ import com.subtracks.ui.components.rememberViewportFill
import com.subtracks.ui.theme.ArtworkColors
import com.subtracks.ui.theme.ArtworkTheme
import com.subtracks.ui.theme.HeroGradient
import com.subtracks.ui.theme.gradientColorAt
import com.subtracks.ui.theme.rememberArtworkColors
import org.koin.compose.koinInject
import org.koin.compose.viewmodel.koinViewModel
@@ -130,8 +131,9 @@ fun AlbumDetailScreen(
BoxWithConstraints(modifier.fillMaxSize().background(Color.Black)) {
val listState = rememberLazyListState()
val fill = rememberViewportFill(listState)
val gradientHeight = maxHeight * GRADIENT_SCREENS
val density = LocalDensity.current
val gradientHeight = maxHeight * GRADIENT_SCREENS
val gradientHeightPx = with(density) { gradientHeight.toPx() }
val statusBarTop = WindowInsets.statusBars.getTop(density)
val navBarBottom = WindowInsets.navigationBars.getBottom(density)
val statusBarDp = with(density) { statusBarTop.toDp() }
@@ -162,6 +164,9 @@ fun AlbumDetailScreen(
animationSpec = tween(durationMillis = 600),
label = "gradientAlpha",
)
val barColor =
artwork?.gradientColorAt(((scrollPx + barHeightPx / 2f) / gradientHeightPx).coerceIn(0f, 1f))
?: Color.Black
HeroGradient(
colors = artwork,
@@ -223,24 +228,6 @@ fun AlbumDetailScreen(
).alpha(1f - barFraction),
)
Box(
Modifier
.align(Alignment.TopStart)
.fillMaxWidth()
.height(with(density) { barHeightPx.toDp() })
.clipToBounds()
.alpha(barFraction),
) {
HeroGradient(
colors = artwork,
modifier =
Modifier
.fillMaxWidth()
.requiredHeight(gradientHeight)
.offset { IntOffset(0, -scrollPx.roundToInt()) },
)
}
TopAppBar(
title = {
Text(
@@ -260,6 +247,7 @@ fun AlbumDetailScreen(
modifier =
Modifier
.align(Alignment.TopStart)
.background(barColor.copy(alpha = barFraction))
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
@@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.graphics.luminance
import androidx.palette.graphics.Palette
import coil3.SingletonImageLoader
@@ -92,20 +93,39 @@ fun artworkColorsFromSeeds(
val secondary =
secondarySeed?.let { seed ->
val color = Color(seed or 0xFF000000.toInt())
val (sh, ss, sl) = color.toHsl()
if (sl > 0.55f) Color.hsl(sh, ss, 0.30f) else color
} ?: tone(hue, s, 0.08f)
val (sh, ss, sl) = Color(seed or 0xFF000000.toInt()).toHsl()
Color.hsl(
blendHue(sh, hue, 0.5f),
ss.coerceAtLeast(s * 0.7f).coerceAtMost(0.9f),
sl.coerceIn(0.34f, 0.56f),
)
} ?: tone(hue, s, 0.40f)
return ArtworkColors(
scheme = scheme,
gradientHigh = tone(hue, (s * 0.6f).coerceAtMost(0.50f), 0.22f),
gradientLow = tone(hue, s * 0.30f, 0.03f),
accents = listOf(tone(hue, s * 0.8f, 0.90f), secondary),
gradientHigh = tone(hue, (s * 0.85f).coerceAtMost(0.65f), 0.30f),
gradientLow = tone(hue, s * 0.45f, 0.04f),
accents = listOf(tone(hue, s, 0.72f), secondary),
blobSeed = primarySeed,
)
}
fun ArtworkColors.gradientColorAt(fraction: Float): Color {
val t = fraction.coerceIn(0f, 1f)
val base = lerp(gradientHigh, gradientLow, t)
val fade = ((t - GRADIENT_FADE_START) / (1f - GRADIENT_FADE_START)).coerceIn(0f, 1f)
return lerp(base, Color.Black, fade)
}
private fun blendHue(
from: Float,
to: Float,
fraction: Float,
): Float {
val delta = ((to - from + 540f) % 360f) - 180f
return (from + delta * fraction + 360f) % 360f
}
@Composable
fun rememberArtworkColors(ref: CoverArtRef?): ArtworkColors? {
val seeds by rememberArtworkSeed(ref)