make the artist header full-bleed at a fixed height

This commit is contained in:
austinried
2026-10-04 00:29:52 +00:00
parent dd660597fb
commit f3ad1a0ba2
@@ -1,8 +1,9 @@
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.BoxWithConstraints import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
@@ -11,8 +12,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
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.items import androidx.compose.foundation.lazy.grid.itemsIndexed
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
@@ -20,13 +22,16 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
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
@@ -37,6 +42,9 @@ import com.subtracks.ui.components.CoverArt
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
private val ART_HEIGHT = 320.dp
private val SCRIM_HEIGHT = 128.dp
@Composable @Composable
fun ArtistDetailRoute( fun ArtistDetailRoute(
artistId: String, artistId: String,
@@ -68,70 +76,91 @@ fun ArtistDetailScreen(
onAlbumClick: (Album) -> Unit, onAlbumClick: (Album) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Scaffold( Box(modifier.fillMaxSize()) {
modifier = modifier, LazyVerticalGrid(
topBar = { columns = GridCells.Fixed(2),
TopAppBar( contentPadding = PaddingValues(bottom = 16.dp),
title = { horizontalArrangement = Arrangement.spacedBy(12.dp),
Text( verticalArrangement = Arrangement.spacedBy(16.dp),
text = artist?.name.orEmpty(), modifier = Modifier.fillMaxSize(),
style = MaterialTheme.typography.headlineLarge, ) {
maxLines = 1, item(span = { GridItemSpan(maxLineSpan) }) {
overflow = TextOverflow.Ellipsis, Box(Modifier.fillMaxWidth().height(ART_HEIGHT)) {
CoverArt(
ref = art,
name = artist?.name.orEmpty(),
modifier = Modifier.fillMaxSize(),
) )
}, Box(
navigationIcon = { modifier =
IconButton(onClick = onBack) { Modifier
Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back") .fillMaxWidth()
} .height(SCRIM_HEIGHT)
}, .background(
) Brush.verticalGradient(listOf(Color.Black.copy(alpha = 0.6f), Color.Transparent)),
}, ),
) { padding -> )
BoxWithConstraints(Modifier.padding(padding).fillMaxSize()) { }
val artHeight = maxHeight * 0.3f }
Column(Modifier.fillMaxSize()) { item(span = { GridItemSpan(maxLineSpan) }) {
CoverArt(
ref = art,
name = artist?.name.orEmpty(),
modifier = Modifier.fillMaxWidth().height(artHeight),
)
Text( Text(
text = "${albums.size} albums", text = "${albums.size} albums",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 4.dp),
) )
LazyVerticalGrid( }
columns = GridCells.Fixed(2), itemsIndexed(albums, key = { _, album -> album.id }) { index, album ->
contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp), Column(
horizontalArrangement = Arrangement.spacedBy(12.dp), modifier =
verticalArrangement = Arrangement.spacedBy(16.dp), Modifier
modifier = Modifier.fillMaxWidth().weight(1f), .padding(
start = if (index % 2 == 0) 16.dp else 0.dp,
end = if (index % 2 == 1) 16.dp else 0.dp,
).clickable { onAlbumClick(album) },
) { ) {
items(albums, key = { it.id }) { album -> CoverArt(
Column(Modifier.clickable { onAlbumClick(album) }) { ref = coverArt(album.coverArt, false),
CoverArt( name = album.name,
ref = coverArt(album.coverArt, false), modifier = Modifier.fillMaxWidth().aspectRatio(1f).clip(RoundedCornerShape(2.dp)),
name = album.name, )
modifier = Modifier.fillMaxWidth().aspectRatio(1f).clip(RoundedCornerShape(2.dp)), Text(
) text = album.name,
Text( style = MaterialTheme.typography.bodyMedium,
text = album.name, maxLines = 1,
style = MaterialTheme.typography.bodyMedium, overflow = TextOverflow.Ellipsis,
maxLines = 1, modifier = Modifier.padding(top = 6.dp),
overflow = TextOverflow.Ellipsis, )
modifier = Modifier.padding(top = 6.dp), Text(
) text = album.year?.takeIf { it > 0 }?.toString() ?: "\u00A0",
Text( style = MaterialTheme.typography.bodySmall,
text = album.year?.takeIf { it > 0 }?.toString() ?: "\u00A0", color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodySmall, )
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
} }
} }
} }
TopAppBar(
title = {
Text(
text = artist?.name.orEmpty(),
style = MaterialTheme.typography.headlineLarge,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
navigationIcon = {
IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, contentDescription = "Back")
}
},
colors =
TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
titleContentColor = Color.White,
navigationIconContentColor = Color.White,
),
modifier = Modifier.align(Alignment.TopStart),
)
} }
} }