feat: enhance NuvioScreenHeader with animated title transitions and dynamic header title in SearchScreen

This commit is contained in:
tapframe 2026-03-11 22:25:12 +05:30
parent 160e0a8c47
commit 9366f09292
2 changed files with 31 additions and 6 deletions

View file

@ -1,5 +1,9 @@
package com.nuvio.app.core.ui
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -101,11 +105,17 @@ fun NuvioScreenHeader(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom,
) {
Text(
text = title,
style = MaterialTheme.typography.displayLarge,
color = MaterialTheme.colorScheme.onBackground,
)
AnimatedContent(
targetState = title,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = "screen_header_title",
) { currentTitle ->
Text(
text = currentTitle,
style = MaterialTheme.typography.displayLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(2.dp),
verticalAlignment = Alignment.CenterVertically,

View file

@ -16,6 +16,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
@ -55,6 +56,20 @@ fun SearchScreen(
var query by rememberSaveable { mutableStateOf("") }
var headerHeightPx by remember { mutableIntStateOf(0) }
val listState = rememberLazyListState()
val headerTitle by remember(query, listState, headerHeightPx) {
derivedStateOf {
if (query.isNotBlank()) {
"Search"
} else {
val discoverInFocus = when {
listState.firstVisibleItemIndex > 0 -> true
headerHeightPx > 0 -> listState.firstVisibleItemScrollOffset >= (headerHeightPx * 0.65f).toInt()
else -> false
}
if (discoverInFocus) "Discover" else "Search"
}
}
}
val addonRefreshKey = remember(addonsUiState.addons) {
addonsUiState.addons.mapNotNull { addon ->
@ -175,7 +190,7 @@ fun SearchScreen(
.padding(bottom = 12.dp)
.onSizeChanged { headerHeightPx = it.height },
) {
NuvioScreenHeader(title = "Search")
NuvioScreenHeader(title = headerTitle)
Spacer(modifier = Modifier.height(12.dp))
NuvioInputField(
value = query,