728x90
컴포즈에서 하단에 4칸짜리 탭을 구현해 보겠습니다.
먼저 gradle에 아래 navigation 의존성 추가가 필요합니다.
implementation("androidx.navigation:navigation-compose:2.8.1")
implementation("androidx.compose.material3:material3:1.2.1")
탭을 구성하기 위해서는 NavigationBar, NavigationGraph, 각 탭 별 Screen Class가 필요합니다.
그리고 화면에서 NavController를 통해 등록된 화면 간의 이동을 제어하게 됩니다.
먼저 필요한 화면에 대한 기본 데이터(route, title, icon....)들을 sealed class로 정의해 줍니다.
sealed class Screen(val route: String, val title: String, val icon: ImageVector) {
data object Home : Screen("home", "Home", Icons.Default.Home)
data object Notes : Screen("notes", "Notes", Icons.Default.Search)
data object Daily : Screen("daily", "Daily", Icons.Default.Check)
data object Settings : Screen("settings", "Settings", Icons.Default.Settings)
}
그리고 sealed class가 선언된 해당 파일에서 NavigationBar, NavigationGraph도 마저 구성해 줍니다.
@Composable
fun BottomNavBar(navController: NavController) {
val items = listOf(
Screen.Home,
Screen.Notes,
Screen.Daily,
Screen.Settings
)
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
items.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
imageVector = screen.icon,
contentDescription = screen.title
)
},
label = { Text(screen.title) },
selected = currentRoute == screen.route,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
각 NavigationBarItem을 클릭하면 controller는 선택된 screen의 고유 id 값인 route를 통해 탭을 전환하게 됩니다.
@Composable
fun NavigationGraph(
navController: NavHostController,
dataViewModel: DataViewModel,
paddingValues: PaddingValues) {
NavHost(navController, startDestination = Screen.Home.route) {
composable(Screen.Home.route) { HomeScreen(dataViewModel, paddingValues) }
composable(Screen.Notes.route) { NotesScreen() }
composable(Screen.Daily.route) { DailyScreen() }
composable(Screen.Settings.route) { SettingsScreen() }
}
}
NavGraph에서는 실제로 필요한 화면 컴포저블을 NavHost에 등록합니다.
NavHost는 Controller가 작동할 때, route에 따라 화면 전환을 제공하게 됩니다.
@Composable
fun HomeScreen(viewModel: DataViewModel, paddingValues: PaddingValues) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentAlignment = Alignment.Center
) {
MindBankTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MainScreen(viewModel)
}
}
}
}
@Composable
fun NotesScreen() {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("Notes Screen")
}
}
....
Screen 화면을 목적에 맞게 구성해 줍니다.
참고로 paddingValues를 인자로 넘겨받으면 하단 탭 높이만큼의 padding을 각 화면에 전달하여 컴포넌트가 가려지지 않도록 할 수 있습니다!
이제 Navigation을 적용해 줄 Activity에 아래와 같이 구성하면 완료입니다.
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val dataViewModel: DataViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
Scaffold(
bottomBar = { BottomNavBar(navController = navController) }
) { paddingValues ->
NavigationGraph(navController, dataViewModel, paddingValues)
}
}
}
}
728x90