Jetpack Navigation + BottomNavigationBar 구현하기
1. Jetpack Navigation
사실 Jetpack Navigation에 대해서는 이전에도 한번 포스트를 쓴 적이 있다.
Navigation은 크게 3가지 요소로 이루어져 있다.
NavController
- 대상(즉, 앱의 화면) 간 이동을 담당하는데, 탐색 동작을 처리하는 역할
- 대상을 탐색하고 딥 링크를 처리하며 대상 백 스택을 관리하는 등의 여러 메소드를 제공
NavGraph
- 이동할 컴포저블 대상의 매핑을 담당
- 앱 내의 화면 연결을 보여주는 일종의 지도 역할을 한다.
NavHost
- 현재 탐색 대상(navigation destination)이 포함된 UI 요소
- NavGraph의 현재 대상을 표시하는 컨테이너 역할을 하는 컴포저블
2. BottomNavigationBar 구현하기
이제 위에서 설명한 Navigation과 Compose를 활용해 BottomNavigationBar를 구현해보자.
gradle에 라이브러리 추가
dependencies {
implementation("androidx.navigation:navigation-compose:2.7.7")
}
Bottom Navigation으로 이동할 화면 생성
필자는 여기서 Home, Rating, Profile 3개의 화면을 만들어주었다.
@Composable
fun HomeScreen() {
Text(text = "Home")
}
@Composable
fun RatingScreen() {
Text(text = "Rating")
}
@Composable
fun ProfileScreen() {
Text(text = "Profile")
}
BottomNavItem 생성.
Bottom Navigation으로 이동할 item 객체 클래스 BottomNavItem 클래스를 생성하고,
그 자식으로 Home, Rating, Profile 을 추가한다.
sealed class BottomNavItem(
@StringRes val title: Int,
@DrawableRes val icon: Int,
val screenRoute: String
) {
object Home : BottomNavItem(R.string.home, R.drawable.ic_home, NavScreens.Home.name)
object Rating : BottomNavItem(R.string.rating, R.drawable.ic_rating, NavScreens.Rating.name)
object Profile : BottomNavItem(R.string.profile, R.drawable.ic_profile, NavScreens.Profile.name)
}
NavHost, NavGraph 생성.
NavHost 함수의 NavGraphBuilder 를 통해서 NavGraph를 생성할 수 있다.
@Composable
private fun MyNavHost(
modifier: Modifier = Modifier,
navController: NavHostController,
startDestination: String
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
...
composable(route = NavScreens.Home.name) {
HomeScreen(
onSearchClicked = { navController.navigate(NavScreens.Search.name) }
)
}
composable(route = NavScreens.Rating.name) {
RatingScreen()
}
composable(route = NavScreens.Profile.name) {
ProfileScreen()
}
composable(route = NavScreens.Search.name) {
SearchScreen()
}
}
}
Bottom Navigation 생성
@Composable private fun MyBottomNavigation( modifier: Modifier = Modifier, navController: NavHostController ) { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route val items = listOf( BottomNavItem.Home, BottomNavItem.Rating, BottomNavItem.Profile ) NavigationBar { items.forEach { item -> NavigationBarItem( selected = currentRoute == item.screenRoute, label = { Text( text = stringResource(id = item.title), style = TextStyle( fontSize = 12.sp ) ) }, icon = { Icon( painter = painterResource(id = item.icon), contentDescription = stringResource(id = item.title) ) }, onClick = { navController.navigate(item.screenRoute) { navController.graph.startDestinationRoute?.let { popUpTo(it) { saveState = true } } launchSingleTop = true restoreState = true } }, ) } } }
BottomNavigationBar를 그리는 앱 화면 구성
@Composable
fun MyApp() {
val navController = rememberNavController()
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
...
},
bottomBar = {
MyBottomNavigation(navController = navController)
}
) {
Box(modifier = Modifier.padding(it)) {
MyNavHost(
navController = navController,
startDestination = NavScreens.Home.name
)
}
}
}
댓글
댓글 쓰기