From 87dca7a6df073aecd3e6263c56d0f3ac1990c640 Mon Sep 17 00:00:00 2001 From: nk Date: Sun, 7 Jun 2026 17:33:35 +0300 Subject: [PATCH] =?UTF-8?q?feat(filters):=20=D1=87=D0=B8=D0=BF=D1=8B=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=82=D0=B2=D0=BE=D1=80=D1=8F=D1=8E=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=BF=D0=BE=D0=B4=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BA=D0=BE=D0=B9-=D0=BA=D0=B0=D1=82=D0=B5=D0=B3=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=B5=D0=B9=20(fade=20left=20edge)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Кнопка-категории теперь ПОВЕРХ чипов (Box-оверлей), чипы идут во всю ширину с отступом слева под кнопку. У левого края — затухание прозрачности (Modifier. fadingStartEdge: graphicsLayer Offscreen + horizontalGradient BlendMode.DstIn), так чипы при прокрутке влево красиво уплывают под кнопку и растворяются, а не обрезаются. FilterChips/GenreSelector получили параметр contentPadding. Экраны Радио и Чарты. --- .../com/radiola/ui/charts/ChartsScreen.kt | 26 ++++++++++------ .../com/radiola/ui/components/FilterChips.kt | 31 +++++++++++++++++-- .../com/radiola/ui/stations/StationsScreen.kt | 23 +++++++++----- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/radiola/ui/charts/ChartsScreen.kt b/app/src/main/java/com/radiola/ui/charts/ChartsScreen.kt index 232e4ba..cea287c 100644 --- a/app/src/main/java/com/radiola/ui/charts/ChartsScreen.kt +++ b/app/src/main/java/com/radiola/ui/charts/ChartsScreen.kt @@ -46,6 +46,7 @@ import com.radiola.domain.model.StatPoint import com.radiola.domain.model.TrackStats import com.radiola.ui.components.CategoryPicker import com.radiola.ui.components.EmptyState +import com.radiola.ui.components.fadingStartEdge import com.radiola.ui.components.PopularityChart import com.radiola.ui.components.crossfadeModel import com.radiola.ui.components.serviceLogoRes @@ -102,19 +103,23 @@ fun ChartsScreen( // Фильтр по жанру (если бэкенд уже накопил жанры) if (genres.isNotEmpty()) { Spacer(Modifier.height(10.dp)) - Row(verticalAlignment = Alignment.CenterVertically) { + Box(modifier = Modifier.fillMaxWidth().height(44.dp)) { + GenreSelector( + genres = genres, + selected = selectedGenre, + onSelect = viewModel::selectGenre, + contentPadding = PaddingValues(start = 70.dp, end = 20.dp), + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .fadingStartEdge(62.dp) + ) CategoryPicker( title = "Стиль музыки", items = genres, selected = selectedGenre, onSelect = viewModel::selectGenre, - modifier = Modifier.padding(start = 20.dp) - ) - GenreSelector( - genres = genres, - selected = selectedGenre, - onSelect = viewModel::selectGenre, - modifier = Modifier.weight(1f) + modifier = Modifier.align(Alignment.CenterStart).padding(start = 20.dp) ) } } @@ -225,12 +230,13 @@ private fun GenreSelector( genres: List, selected: String?, onSelect: (String?) -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(horizontal = 20.dp) ) { LazyRow( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(9.dp), - contentPadding = PaddingValues(horizontal = 20.dp) + contentPadding = contentPadding ) { item { PeriodChip( diff --git a/app/src/main/java/com/radiola/ui/components/FilterChips.kt b/app/src/main/java/com/radiola/ui/components/FilterChips.kt index 6f63dde..bd0d751 100644 --- a/app/src/main/java/com/radiola/ui/components/FilterChips.kt +++ b/app/src/main/java/com/radiola/ui/components/FilterChips.kt @@ -20,18 +20,45 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawWithContent +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.CompositingStrategy +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.radiola.ui.theme.Motion import com.radiola.ui.theme.RadiolaTheme +/** + * Плавное затухание содержимого у ЛЕВОГО края (прозрачность) на ширину [width]. + * Чипы, заезжая под кнопку-«категории», красиво растворяются, а не обрезаются. + */ +fun Modifier.fadingStartEdge(width: Dp): Modifier = this + .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } + .drawWithContent { + drawContent() + val w = width.toPx().coerceAtMost(size.width) + drawRect( + brush = Brush.horizontalGradient( + colorStops = arrayOf( + 0f to Color.Transparent, + (w / size.width) to Color.Black + ) + ), + blendMode = BlendMode.DstIn + ) + } + @Composable fun FilterChips( tags: List, selectedTag: String?, onTagSelected: (String?) -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp) ) { val listState = rememberLazyListState() // Доводим выбранный чип в зону видимости (важно при свайп-переключении). @@ -43,7 +70,7 @@ fun FilterChips( modifier = modifier, state = listState, horizontalArrangement = Arrangement.spacedBy(9.dp), - contentPadding = PaddingValues(horizontal = 16.dp) + contentPadding = contentPadding ) { item { Chip(label = "Все", selected = selectedTag == null) { onTagSelected(null) } diff --git a/app/src/main/java/com/radiola/ui/stations/StationsScreen.kt b/app/src/main/java/com/radiola/ui/stations/StationsScreen.kt index ac412ff..9bedf69 100644 --- a/app/src/main/java/com/radiola/ui/stations/StationsScreen.kt +++ b/app/src/main/java/com/radiola/ui/stations/StationsScreen.kt @@ -178,19 +178,26 @@ fun StationsScreen( ) .padding(top = 2.dp, bottom = 12.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically) { + Box(modifier = Modifier.fillMaxWidth().height(44.dp)) { + // Чипы во всю ширину, но с отступом слева под кнопку; у левого + // края — затухание прозрачности (чипы «уплывают» под кнопку). + FilterChips( + tags = tags, + selectedTag = selectedTag, + onTagSelected = viewModel::onTagSelected, + contentPadding = PaddingValues(start = 66.dp, end = 16.dp), + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center) + .fadingStartEdge(60.dp) + ) + // Кнопка-категории — поверх чипов, слева. CategoryPicker( title = "Категории", items = tags, selected = selectedTag, onSelect = viewModel::onTagSelected, - modifier = Modifier.padding(start = 16.dp) - ) - FilterChips( - tags = tags, - selectedTag = selectedTag, - onTagSelected = viewModel::onTagSelected, - modifier = Modifier.weight(1f) + modifier = Modifier.align(Alignment.CenterStart).padding(start = 16.dp) ) } }