implementation 'androidx.navigation:navigation-compose:2.4.0-alpha08'
composable()
메소드로 시작 경로와 라우트를 정의한다.
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable(route = "home") { Home() }
composable(route = "search") { Search() }
}
@Composable
fun Home(navController: NavController) {
Button(onClick = { navController.navigate("search") }) {
Text(text = "Click")
}
}
'slug' 라는 string 타입의 argument 를 사용하여 HomeDetail로 이동하는 예제
NavHost(startDestination = "home/{slug}") {
composable(
"home/{slug}",
arguments = listOf(navArgument("slug") { type = NavType.StringType })
) { backStackEntry ->
val slug = requireNotNull(backStackEntry.arguments).getString("slug")
HomeDetail(navController, slug)
}
}
BottomBar()
의 네비게이션과 상세 화면으로 이동하기 위한 예제.
네비게이션 규모가 커질수록 NavGraphBuilder()
로 중첩 네비게이션을 쓰는게 좋다.
sealed class 만들기
sealed class NavItem(
@StringRes val title: Int,
val icon: ImageVector,
val route: String
){
object Hospital : NavItem(R.string.nav_hospital, Icons.Filled.LocalHospital, "hospital")
object Article : NavItem(R.string.nav_article, Icons.Filled.Article, "article")
}
addHomeGraph
fun NavGraphBuilder.addHomeGraph(
navController: NavHostController,
onClickHospital: (String, NavBackStackEntry) -> Unit,
onClickArticle: (String, NavBackStackEntry) -> Unit
) {
composable(NavItem.Hospital.route) {
Hospitals(navController, onClick = { slug ->
onClickHospital(slug, it)
})
}
composable(NavItem.Article.route) {
Article(navController, onClick = { slug ->
onClickArticle(slug, it)
})
}
}
mainNavGraph
fun NavGraphBuilder.mainNavGraph(
navController: NavHostController,
onClickHospital: (String, NavBackStackEntry) -> Unit,
onClickArticle: (String, NavBackStackEntry) -> Unit
) {
navigation(
route = "home",
startDestination = NavItem.Hospital.route
) {
addHomeGraph(navController, onClickHospital, onClickDoctor, onClickDeal, onClickArticle)
}
composable(
"hospital_detail/{slug}",
arguments = listOf(navArgument("slug") { type = NavType.StringType })
) { backStackEntry ->
val slug = requireNotNull(backStackEntry.arguments).getString("slug")
HospitalDetail(navController, slug)
}
composable(
"article_detail/{slug}",
arguments = listOf(navArgument("slug") { type = NavType.StringType })
) { backStackEntry ->
val slug = requireNotNull(backStackEntry.arguments).getString("slug")
ArticleDetail(navController, slug)
}
}
View
@Composable
fun MainContent() {
val navController = rememberNavController()
val navBackStackEntry by appState.navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route?.substringBeforeLast("/")
Scaffold(
topBar = { TopBar(navController) },
bottomBar = { BottomBar(navController) },
floatingActionButton = { FloatingChatButton() }
) {
NavHost(navController = navController, startDestination = "home") {
mainNavGraph(
navController = navController,
onClickHospital = {navController.navigate("hospital_detail/$slug")},
onClickArticle = {navController.navigate("article_detail/$slug")}
)
}
}
}
Detail Page
@Composable
fun HospitalDetail(
navController: NavHostController, slug: String
) {
val viewModel: HospitalVM = viewModel()
val hospital = viewModel.hospital.observeAsState().value
val loadingState = viewModel.loading.observeAsState().value
LaunchedEffect(key1 = "GET_HOSPITAL_DETAIL") {
slug?.let {
viewModel.fetchHospitalItem(slug)
}
}
if (loadingState == true) {
LoadingBar()
} else {
hospital?.let {
HospitalDetailView(hospital)
}
}
}
참고
https://developer.android.com/jetpack/compose/navigation#bottom-nav
https://github.com/android/compose-samples/tree/main/Jetsnack