overlay the artist name on the image with a fading header

This commit is contained in:
austinried
2026-10-04 00:29:52 +00:00
parent c6d837ae0d
commit d337e49a64
2 changed files with 40 additions and 17 deletions
@@ -1,5 +1,6 @@
package com.subtracks.ui.library package com.subtracks.ui.library
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -15,6 +16,7 @@ import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.ArrowBack
@@ -26,7 +28,9 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
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.BlurredEdgeTreatment import androidx.compose.ui.draw.BlurredEdgeTreatment
@@ -35,6 +39,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
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.platform.LocalDensity
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -78,8 +83,30 @@ fun ArtistDetailScreen(
onAlbumClick: (Album) -> Unit, onAlbumClick: (Album) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val listState = rememberLazyGridState()
val artHeightPx = with(LocalDensity.current) { ART_HEIGHT.toPx() }
val barFraction by remember {
derivedStateOf {
if (listState.firstVisibleItemIndex > 0) {
1f
} else {
(listState.firstVisibleItemScrollOffset / artHeightPx).coerceIn(0f, 1f)
}
}
}
val nameStyle =
MaterialTheme.typography.headlineLarge.copy(
shadow =
Shadow(
color = Color.Black.copy(alpha = 0.8f),
offset = Offset(0f, 2f),
blurRadius = 10f,
),
)
Box(modifier.fillMaxSize()) { Box(modifier.fillMaxSize()) {
LazyVerticalGrid( LazyVerticalGrid(
state = listState,
columns = GridCells.Fixed(2), columns = GridCells.Fixed(2),
contentPadding = PaddingValues(bottom = 16.dp), contentPadding = PaddingValues(bottom = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),
@@ -93,6 +120,14 @@ fun ArtistDetailScreen(
name = artist?.name.orEmpty(), name = artist?.name.orEmpty(),
modifier = Modifier.fillMaxWidth().height(ART_HEIGHT), modifier = Modifier.fillMaxWidth().height(ART_HEIGHT),
) )
Text(
text = artist?.name.orEmpty(),
style = nameStyle,
color = Color.White,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.align(Alignment.BottomStart).padding(16.dp),
)
} }
} }
itemsIndexed(albums, key = { _, album -> album.id }) { index, album -> itemsIndexed(albums, key = { _, album -> album.id }) { index, album ->
@@ -130,15 +165,8 @@ fun ArtistDetailScreen(
title = { title = {
Text( Text(
text = artist?.name.orEmpty(), text = artist?.name.orEmpty(),
style = style = nameStyle,
MaterialTheme.typography.headlineLarge.copy( color = Color.White.copy(alpha = barFraction),
shadow =
Shadow(
color = Color.Black.copy(alpha = 0.8f),
offset = Offset(0f, 2f),
blurRadius = 10f,
),
),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
@@ -163,13 +191,8 @@ fun ArtistDetailScreen(
} }
} }
}, },
colors = colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
TopAppBarDefaults.topAppBarColors( modifier = Modifier.align(Alignment.TopStart).background(Color.Black.copy(alpha = barFraction)),
containerColor = Color.Transparent,
titleContentColor = Color.White,
navigationIconContentColor = Color.White,
),
modifier = Modifier.align(Alignment.TopStart),
) )
} }
} }
@@ -204,7 +204,7 @@ fun LibraryScreen(
tint = MaterialTheme.colorScheme.onBackground, tint = MaterialTheme.colorScheme.onBackground,
modifier = modifier =
Modifier Modifier
.padding(start = 12.dp, top = titleTop + (titleLineHeight - logoSize) / 2) .padding(start = 20.dp, top = titleTop + (titleLineHeight - logoSize) / 2)
.size(logoSize), .size(logoSize),
) )
Text( Text(