From 3c90adae6a1607490a06533767bd126a0d0895d4 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Tue, 26 May 2026 12:04:33 +0800 Subject: [PATCH] fix: use offset+clipToBounds instead of graphicsLayer alpha for tab keep-alive Hidden tabs with graphicsLayer{alpha=0f} still intercepted touch events. Replaced with offset(x=2000.dp) + parent clipToBounds() so hidden composables are off-screen and cannot capture touches meant for the visible tab. Co-Authored-By: Claude Opus 4.7 --- .../top/yeij/cyrene/ui/navigation/NavGraph.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/top/yeij/cyrene/ui/navigation/NavGraph.kt b/app/src/main/java/top/yeij/cyrene/ui/navigation/NavGraph.kt index 9f3d9cf..51b8182 100644 --- a/app/src/main/java/top/yeij/cyrene/ui/navigation/NavGraph.kt +++ b/app/src/main/java/top/yeij/cyrene/ui/navigation/NavGraph.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Chat @@ -21,7 +22,8 @@ import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -145,28 +147,29 @@ fun MainScreen( modifier = Modifier .weight(1f) .fillMaxHeight() + .clipToBounds() .background(MaterialTheme.colorScheme.background), ) { - // Keep all tabs composed to avoid destroying ChatScreen on tab switch. - // Hidden tabs use graphicsLayer { alpha = 0f } — invisible but alive. + // Keep all tabs alive by offsetting hidden ones off-screen. + // clipToBounds ensures they don't intercept touches outside the visible area. Box( modifier = Modifier .fillMaxSize() - .graphicsLayer { alpha = if (selectedTab == 0) 1f else 0f }, + .offset(x = if (selectedTab == 0) 0.dp else 2000.dp), ) { ChatScreen() } Box( modifier = Modifier .fillMaxSize() - .graphicsLayer { alpha = if (selectedTab == 1) 1f else 0f }, + .offset(x = if (selectedTab == 1) 0.dp else 2000.dp), ) { IoTScreen() } Box( modifier = Modifier .fillMaxSize() - .graphicsLayer { alpha = if (selectedTab == 2) 1f else 0f }, + .offset(x = if (selectedTab == 2) 0.dp else 2000.dp), ) { ProfileScreen( onNavigateToSettings = { navController.navigate(Routes.SETTINGS) },