scroll the artist detail background and match its bar to the hero

The artist background used a static gradient and a scroll-0 bar colour. It now scrolls with
the grid (fading to a dark single colour) and the bar colour comes from heroBarColor at the
real scroll, like the album/playlist hero. The gradient's scroll origin is the hero image
bottom, since the image is full-width and covers the top.
This commit is contained in:
austinried
2026-10-04 00:29:59 +00:00
parent dcdcf553e2
commit 63279dec50
@@ -41,7 +41,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
@@ -51,6 +53,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@@ -159,6 +162,20 @@ fun ArtistDetailScreen(
} }
} }
} }
var imageHeightPx by remember { mutableFloatStateOf(0f) }
var albumHeightPx by remember { mutableFloatStateOf(0f) }
val albumRowGapPx = with(density) { 16.dp.toPx() }
val scrollPx by remember {
derivedStateOf {
val index = listState.firstVisibleItemIndex
val offset = listState.firstVisibleItemScrollOffset.toFloat()
if (index <= 0) {
offset
} else {
imageHeightPx + (albumHeightPx + albumRowGapPx) * ((index - 1) / 2) + offset
}
}
}
val nameTextStyle = MaterialTheme.typography.headlineLarge val nameTextStyle = MaterialTheme.typography.headlineLarge
val imageNameStyle = val imageNameStyle =
nameTextStyle.copy( nameTextStyle.copy(
@@ -178,10 +195,10 @@ fun ArtistDetailScreen(
BoxWithConstraints(modifier.fillMaxSize().background(Color.Black)) { BoxWithConstraints(modifier.fillMaxSize().background(Color.Black)) {
val screenHeightPx = with(density) { maxHeight.toPx() } val screenHeightPx = with(density) { maxHeight.toPx() }
val barHeightPx = with(density) { barHeight.toPx() } val barHeightPx = with(density) { barHeight.toPx() }
val barColor = heroBarColor(effectiveArtwork, 0f, barHeightPx, screenHeightPx) val barColor = heroBarColor(effectiveArtwork, scrollPx, barHeightPx, screenHeightPx)
HeroGradient( HeroGradient(
colors = effectiveArtwork, colors = effectiveArtwork,
scrollPx = { 0f }, scrollPx = { scrollPx - imageHeightPx },
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) )
LazyVerticalGrid( LazyVerticalGrid(
@@ -193,7 +210,12 @@ fun ArtistDetailScreen(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) { ) {
item(span = { GridItemSpan(maxLineSpan) }) { item(span = { GridItemSpan(maxLineSpan) }) {
Box(Modifier.fillMaxWidth().padding(bottom = 12.dp)) { Box(
Modifier
.fillMaxWidth()
.onSizeChanged { imageHeightPx = it.height.toFloat() }
.padding(bottom = 12.dp),
) {
CoverArt( CoverArt(
ref = art, ref = art,
name = artist?.name.orEmpty(), name = artist?.name.orEmpty(),
@@ -237,7 +259,7 @@ fun ArtistDetailScreen(
).combinedClickable( ).combinedClickable(
onClick = { onAlbumClick(album) }, onClick = { onAlbumClick(album) },
onLongClick = { onAlbumLongClick(MenuTarget.Album(album, coverArt(album.coverArt, true))) }, onLongClick = { onAlbumLongClick(MenuTarget.Album(album, coverArt(album.coverArt, true))) },
), ).onSizeChanged { albumHeightPx = it.height.toFloat() },
) { ) {
Box { Box {
CoverArt( CoverArt(