fix(navigation): keep Home composed while article is open

Article was an AnimatedContent target: opening it disposed Home, and returning from it recreated the whole results list in a single frame. The article screen now renders as a full-screen AnimatedVisibility overlay above Home, which stays composed for the whole article session.
This commit is contained in:
OneWay committed 2026-09-25 23:59:45 +08:00
1 parent c7c080939c
commit ed4a4436b8
1 file changed
+30 -10
@@ -2,16 +2,22 @@ package com.example.research.ui.navigation
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfoV2
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.*
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
import com.example.research.feature.search.SearchAction
@@ -101,10 +107,11 @@ fun AppNavigation(
val effectiveScreen = when {
currentScreen == Screen.About -> Screen.About
currentScreen == Screen.Article && articleState == null -> if (shouldShowSettings) Screen.Settings else Screen.Home
shouldShowSettings -> Screen.Settings
else -> currentScreen
currentScreen == Screen.Settings -> Screen.Settings
else -> Screen.Home
}
Box {
AnimatedContent(
targetState = effectiveScreen,
transitionSpec = {
@@ -150,7 +157,27 @@ fun AppNavigation(
onNavigateToAbout = { screenStack.add(Screen.About) }
)
}
Screen.Article -> {
Screen.About -> {
AboutScreen(
onNavigateBack = {
if (screenStack.size > 1) screenStack.removeAt(screenStack.lastIndex)
}
)
}
Screen.Article -> {}
}
}
AnimatedVisibility(
visible = currentScreen == Screen.Article && articleState != null,
enter = fadeIn(tween(180)) + slideInHorizontally(tween(180)) { it / 3 },
exit = fadeOut(tween(180)) + slideOutHorizontally(tween(180)) { it / 3 },
label = "articleOverlay",
) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.surface
) {
ArticleRoute(
searchViewModel = searchViewModel,
onNavigateBack = {
@@ -162,13 +189,6 @@ fun AppNavigation(
}
)
}
Screen.About -> {
AboutScreen(
onNavigateBack = {
if (screenStack.size > 1) screenStack.removeAt(screenStack.lastIndex)
}
)
}
}
}
}