11package com.maazm7d.termuxhub.navigation
22
3- import androidx.compose.foundation.layout.offset
3+ import androidx.compose.animation.AnimatedVisibility
4+ import androidx.compose.animation.fadeIn
5+ import androidx.compose.animation.fadeOut
6+ import androidx.compose.animation.slideInVertically
7+ import androidx.compose.animation.slideOutVertically
8+ import androidx.compose.animation.core.animateFloatAsState
9+ import androidx.compose.foundation.layout.Box
10+ import androidx.compose.foundation.layout.fillMaxSize
411import androidx.compose.foundation.layout.padding
512import androidx.compose.foundation.layout.size
13+ import androidx.compose.foundation.shape.RoundedCornerShape
614import androidx.compose.material3.*
715import androidx.compose.runtime.*
16+ import androidx.compose.ui.Alignment
817import androidx.compose.ui.Modifier
918import androidx.compose.ui.graphics.Color
19+ import androidx.compose.ui.graphics.graphicsLayer
20+ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
21+ import androidx.compose.ui.input.nestedscroll.NestedScrollSource
22+ import androidx.compose.ui.input.nestedscroll.nestedScroll
1023import androidx.compose.ui.unit.dp
1124import androidx.navigation.NavDestination
1225import androidx.navigation.NavDestination.Companion.hierarchy
@@ -22,14 +35,30 @@ fun TermuxHubAppNav(
2235 val backStackEntry by navController.currentBackStackEntryAsState()
2336 val currentDestination: NavDestination ? = backStackEntry?.destination
2437
25- var handledDeepLink by remember { mutableStateOf(false ) }
38+ var deepLinkHandled by remember { mutableStateOf(false ) }
39+ var isBottomBarVisible by remember { mutableStateOf(true ) }
40+
41+ // Detect scroll direction
42+ val scrollBehavior = remember {
43+ object : NestedScrollConnection {
44+ override fun onPreScroll (
45+ available : androidx.compose.ui.geometry.Offset ,
46+ source : NestedScrollSource
47+ ): androidx.compose.ui.geometry.Offset {
48+ when {
49+ available.y < - 5f -> isBottomBarVisible = false // scroll down
50+ available.y > 5f -> isBottomBarVisible = true // scroll up
51+ }
52+ return androidx.compose.ui.geometry.Offset .Zero
53+ }
54+ }
55+ }
2656
2757 LaunchedEffect (deepLinkToolId) {
2858 if (deepLinkToolId.isNullOrBlank()) return @LaunchedEffect
29- if (handledDeepLink) return @LaunchedEffect
30-
31- handledDeepLink = true
59+ if (deepLinkHandled) return @LaunchedEffect
3260
61+ deepLinkHandled = true
3362 navController.navigate(" ${Destinations .DETAILS } /$deepLinkToolId " ) {
3463 popUpTo(navController.graph.startDestinationId) {
3564 inclusive = false
@@ -45,51 +74,98 @@ fun TermuxHubAppNav(
4574 }
4675
4776 Scaffold (
48- bottomBar = {
49- if (showBottomBar) {
50- NavigationBar (
51- containerColor = MaterialTheme .colorScheme.surface
52- ) {
53- bottomNavItems.forEach { item ->
54- val isSelected = currentDestination
55- ?.hierarchy
56- ?.any { it.route == item.route } == true
77+ containerColor = Color .Transparent
78+ ) { paddingValues ->
79+ Box (
80+ modifier = Modifier
81+ .fillMaxSize()
82+ .padding(paddingValues)
83+ .nestedScroll(scrollBehavior)
84+ ) {
85+ AppNavHost (
86+ navController = navController,
87+ modifier = Modifier .fillMaxSize()
88+ )
5789
58- NavigationBarItem (
59- selected = isSelected,
60- onClick = {
61- navController.navigate(item.route) {
62- popUpTo(Destinations .TOOLS ) {
63- saveState = true
64- }
65- launchSingleTop = true
66- restoreState = true
90+ AnimatedVisibility (
91+ visible = showBottomBar && isBottomBarVisible,
92+ enter = slideInVertically { it / 2 } + fadeIn(),
93+ exit = slideOutVertically { it / 2 } + fadeOut(),
94+ modifier = Modifier
95+ .align(Alignment .BottomCenter )
96+ .padding(horizontal = 16 .dp, vertical = 20 .dp)
97+ ) {
98+ BottomPillNavBar (
99+ currentDestination = currentDestination,
100+ onNavigate = { route ->
101+ navController.navigate(route) {
102+ popUpTo(Destinations .TOOLS ) {
103+ saveState = true
104+ }
105+ launchSingleTop = true
106+ restoreState = true
107+ }
108+ }
109+ )
110+ }
111+ }
112+ }
113+ }
114+
115+ @Composable
116+ private fun BottomPillNavBar (
117+ currentDestination : NavDestination ? ,
118+ onNavigate : (String ) -> Unit
119+ ) {
120+ Surface (
121+ shape = RoundedCornerShape (32 .dp),
122+ color = MaterialTheme .colorScheme.surface,
123+ tonalElevation = 6 .dp,
124+ shadowElevation = 10 .dp
125+ ) {
126+ NavigationBar (
127+ containerColor = Color .Transparent ,
128+ tonalElevation = 0 .dp
129+ ) {
130+ bottomNavItems.forEach { item ->
131+ val selected = currentDestination
132+ ?.hierarchy
133+ ?.any { it.route == item.route } == true
134+
135+ val scale by animateFloatAsState(
136+ targetValue = if (selected) 1.15f else 1f ,
137+ label = " scale"
138+ )
139+
140+ val alpha by animateFloatAsState(
141+ targetValue = if (selected) 1f else 0.6f ,
142+ label = " alpha"
143+ )
144+
145+ NavigationBarItem (
146+ selected = selected,
147+ onClick = { onNavigate(item.route) },
148+ icon = {
149+ Icon (
150+ imageVector = item.icon,
151+ contentDescription = null ,
152+ modifier = Modifier
153+ .size(if (item.isHome) 26 .dp else 22 .dp)
154+ .graphicsLayer {
155+ scaleX = scale
156+ scaleY = scale
157+ this .alpha = alpha
67158 }
68- },
69- icon = {
70- Icon (
71- imageVector = item.icon,
72- contentDescription = null ,
73- modifier = Modifier
74- .offset(y = if (item.isHome) (- 4 ).dp else 0 .dp)
75- .size(if (item.isHome) 30 .dp else 22 .dp)
76- )
77- },
78- label = null ,
79- colors = NavigationBarItemDefaults .colors(
80- indicatorColor = Color .Transparent ,
81- selectedIconColor = MaterialTheme .colorScheme.primary,
82- unselectedIconColor = MaterialTheme .colorScheme.onSurfaceVariant
83- )
84159 )
85- }
86- }
160+ },
161+ label = null ,
162+ colors = NavigationBarItemDefaults .colors(
163+ indicatorColor = Color .Transparent ,
164+ selectedIconColor = MaterialTheme .colorScheme.primary,
165+ unselectedIconColor = MaterialTheme .colorScheme.onSurfaceVariant
166+ )
167+ )
87168 }
88169 }
89- ) { innerPadding ->
90- AppNavHost (
91- navController = navController,
92- modifier = Modifier .padding(innerPadding)
93- )
94170 }
95171}
0 commit comments