feat: add main nav host best practice

This commit is contained in:
2026-05-27 23:55:28 +03:30
parent c09d79dbbc
commit c8044bfe42
7 changed files with 137 additions and 169 deletions
@@ -36,9 +36,7 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
DrugTheme {
val navController = rememberNavController()
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
AppNavGraph(
// navController = navController,
// modifier = Modifier.padding(innerPadding)
@@ -1,9 +1,18 @@
package com.approagency.drug.navigation
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.approagency.drug.presentation.screens.DrugDetailScreen
import com.approagency.drug.presentation.screens.HomeScreen
import com.approagency.drug.presentation.screens.LabScreen
import com.approagency.drug.presentation.screens.SearchScreen
@Composable
fun AppNavGraph() {
@@ -12,12 +21,51 @@ fun AppNavGraph() {
NavHost(
navController = navController,
startDestination = "main_container"
startDestination = "home"
) {
composable("main_container") {
// ───────────────
// BOTTOM TABS
// ───────────────
MainContainer()
composable("home") {
MainContainer(navController) {
HomeScreen(navController , modifier = Modifier)
}
}
composable("search") {
MainContainer(navController) {
SearchScreen(navController)
}
}
composable("lab") {
MainContainer(navController) {
LabScreen()
}
}
// ───────────────
// GLOBAL SCREEN
// ───────────────
composable(
route = Screen.DrugDetail.route,
arguments = listOf(
navArgument("detailUrl") {
type = NavType.StringType
}
)
) {
val detailUrl =
Uri.decode(it.arguments?.getString("detailUrl") ?: "")
DrugDetailScreen(
navController = navController,
detailUrl = detailUrl
)
}
}
}
@@ -39,62 +39,56 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
@Composable
fun BottomBar(
navController: NavHostController
) {
fun BottomBar(navController: NavHostController) {
val items = listOf(
Triple(MainRoute.HomeGraph, "دارو", Icons.Default.Search),
Triple(MainRoute.SearchGraph, "سرچ", Icons.Rounded.Refresh),
Triple(MainRoute.LabGraph, "آزمایش", Icons.Default.Build)
Triple("home", "دارو", Icons.Default.Search),
Triple("search", "سرچ", Icons.Rounded.Refresh),
Triple("lab", "آزمایش", Icons.Default.Build)
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val currentRoute = navBackStackEntry?.destination?.route
Surface(
tonalElevation = 2.dp,
color = MaterialTheme.colorScheme.surface,
modifier = Modifier
.navigationBarsPadding()
.height(50.dp)
.height(56.dp)
) {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically
) {
Row(modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically) {
items.forEach { item ->
val selected = currentDestination
?.hierarchy
?.any { it.route == item.first.route } == true
val selected = currentRoute == item.first
val color = if (selected)
MaterialTheme.colorScheme.primary
else
MaterialTheme.colorScheme.onSurfaceVariant
val background = if (selected)
MaterialTheme.colorScheme.primary.copy(alpha = 0.12f)
else
Color.Transparent
Box(
modifier = Modifier
.weight(1f)
.padding(horizontal = 8.dp , vertical = 4.dp)
.weight(1f).padding(horizontal = 8.dp , vertical = 4.dp)
.clip(MaterialTheme.shapes.large)
.background(background)
.clickable {
navController.navigate(item.first.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
if (!selected) {
navController.navigate(item.first) {
popUpTo("home") {
saveState = true
}
launchSingleTop = true
restoreState = true
}
launchSingleTop = true
restoreState = true
}
}
.padding(horizontal = 10.dp, vertical = 10.dp),
contentAlignment = Alignment.Center
}.padding(horizontal = 10.dp, vertical = 10.dp),
contentAlignment = Alignment.Center
) {
Row(
@@ -1,51 +1,28 @@
package com.approagency.drug.navigation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.approagency.drug.navigation.graphs.homeGraph
import com.approagency.drug.navigation.graphs.labGraph
import com.approagency.drug.navigation.graphs.searchGraph
@Composable
fun MainContainer() {
fun MainContainer(
navController: NavHostController,
content: @Composable () -> Unit
) {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val showBottomBar = when (currentRoute) {
Screen.Home.route,
Screen.Search.route,
Screen.Lab.route -> true
else -> false
}
Scaffold(
bottomBar = {
if (showBottomBar) {
BottomBar(navController)
}
}
) { padding ->
NavHost(
navController = navController,
startDestination = MainRoute.HomeGraph.route,
modifier =if (showBottomBar ) Modifier.padding(padding) else Modifier
) {
homeGraph(navController)
searchGraph(navController)
labGraph(navController)
Box(modifier = Modifier.padding(padding)) {
content()
}
}
}
@@ -1,28 +1,19 @@
package com.approagency.drug.navigation.graphs
import androidx.compose.ui.Modifier
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.navigation
import com.approagency.drug.navigation.MainRoute
import com.approagency.drug.navigation.Screen
import com.approagency.drug.presentation.screens.HomeScreen
fun NavGraphBuilder.homeGraph(
navController: NavHostController
) {
navigation(
route = MainRoute.HomeGraph.route,
startDestination = Screen.Home.route
) {
composable(Screen.Home.route) {
HomeScreen(
navController = navController , modifier = Modifier
)
}
}
}
//package com.approagency.drug.navigation.graphs
//
//import androidx.compose.ui.Modifier
//import androidx.navigation.NavGraphBuilder
//import androidx.navigation.NavHostController
//import androidx.navigation.compose.composable
//import androidx.navigation.navigation
//import com.approagency.drug.navigation.MainRoute
//import com.approagency.drug.navigation.Screen
//import com.approagency.drug.presentation.screens.HomeScreen
//
//fun NavGraphBuilder.homeGraph(navController: NavHostController) {
//
// composable(MainRoute.HomeGraph.route) {
// HomeScreen(
// navController = navController , modifier = Modifier
// )
// }
//}
@@ -1,25 +1,16 @@
package com.approagency.drug.navigation.graphs
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import androidx.navigation.navigation
import com.approagency.drug.navigation.MainRoute
import com.approagency.drug.navigation.Screen
import com.approagency.drug.presentation.screens.LabScreen
fun NavGraphBuilder.labGraph(
navController: NavHostController
) {
navigation(
route = MainRoute.LabGraph.route,
startDestination = Screen.Lab.route
) {
composable(Screen.Lab.route) {
LabScreen()
}
}
}
//package com.approagency.drug.navigation.graphs
//
//import androidx.navigation.NavGraphBuilder
//import androidx.navigation.NavHostController
//import androidx.navigation.compose.composable
//import androidx.navigation.navigation
//import com.approagency.drug.navigation.MainRoute
//import com.approagency.drug.navigation.Screen
//import com.approagency.drug.presentation.screens.LabScreen
//
//fun NavGraphBuilder.labGraph(navController: NavHostController) {
//
// composable(MainRoute.LabGraph.route) {
// LabScreen()
// }
//}
@@ -1,51 +1,20 @@
package com.approagency.drug.navigation.graphs
import android.net.Uri
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import androidx.navigation.navigation
import com.approagency.drug.navigation.MainRoute
import com.approagency.drug.navigation.Screen
import com.approagency.drug.presentation.screens.DrugDetailScreen
import com.approagency.drug.presentation.screens.SearchScreen
fun NavGraphBuilder.searchGraph(
navController: NavHostController
) {
navigation(
route = MainRoute.SearchGraph.route,
startDestination = Screen.Search.route
) {
composable(Screen.Search.route) {
SearchScreen(
navController = navController
)
}
composable(
route = Screen.DrugDetail.route,
arguments = listOf(
navArgument("detailUrl") {
type = NavType.StringType
}
)
) {
val detailUrl =
Uri.decode(
it.arguments?.getString("detailUrl") ?: ""
)
DrugDetailScreen(
navController = navController,
detailUrl = detailUrl
)
}
}
}
//package com.approagency.drug.navigation.graphs
//
//import android.net.Uri
//import androidx.navigation.NavGraphBuilder
//import androidx.navigation.NavHostController
//import androidx.navigation.NavType
//import androidx.navigation.compose.composable
//import androidx.navigation.navArgument
//import androidx.navigation.navigation
//import com.approagency.drug.navigation.MainRoute
//import com.approagency.drug.navigation.Screen
//import com.approagency.drug.presentation.screens.DrugDetailScreen
//import com.approagency.drug.presentation.screens.SearchScreen
//
//fun NavGraphBuilder.searchGraph(navController: NavHostController) {
//
// composable(MainRoute.SearchGraph.route) {
// SearchScreen(navController)
// }
//}