#1 개요
#1-1 Scaffold의 bottomBar
이전 게시글에서 Scaffold를 만들었다. 해당 Scaffold에는 대부분 앱의 전형적인 구조로서 포함되는 NavigationBar를 넣을 것이다. 그러기 위해서 먼저, NavHost부터 만들어둘 필요가 있다.
#1-2 NavHost 구현
위 게시글에 기반하여 #2의 코드를 작성했다.
#1-3 Destination 구성
1. NutrientInputScreen: 사용자가 먹은 음식에 대해 기록하는 화면
2. StatisticsScreen: 지금까지 기록한 식단에 대한 통계 화면
3. UserInfoScreen: 사용자 자체에 대한 정보 화면
NavHost 및 NavigationBar가 보유할 Destination을 3가지로 상정했다. 나중에 변경될 가능성도 있지만, 현재 시점에서 구현할 것이라고 예상되는 화면이다.
#2 코드
#2-1 모듈 수준 build.gradle.kt 및 lib.versions.toml 수정
plugins {
...
}
android {
...
}
dependencies {
...
// Navigation
implementation(libs.androidx.navigation.runtime.ktx)
implementation(libs.androidx.navigation.compose)
}
Jetpack Compose의 네비게이션 라이브러리를 추가한다.
[versions]
...
navigationRuntimeKtx = "2.8.1"
[libraries]
...
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationRuntimeKtx" }
androidx-navigation-runtime-ktx = { module = "androidx.navigation:navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" }
[plugins]
...
build.gradle에 추가했던 구문을 안드로이드 컴파일러가 해석할 수 있도록 lib.versions.toml도 수정한다.
#2-2 Destination용 @Composable 3개 생성
// in NutrientInputScreen.kt
@Composable
fun NutrientInputScreen(
scope: CoroutineScope,
snackbarHostState: SnackbarHostState
) {
Column(
modifier = Modifier.fillMaxSize()
) {
SampleContent(
text = "NutrientInputScreen",
modifier = Modifier
.fillMaxSize()
.background(Color.LightGray),
scope = scope,
snackbarHostState = snackbarHostState
)
}
}
// in StatisticsScreen.kt
@Composable
fun StatisticsScreen(
scope: CoroutineScope,
snackbarHostState: SnackbarHostState
) {
Column(
modifier = Modifier.fillMaxSize()
) {
SampleContent(
text = "StatisticsScreen",
modifier = Modifier
.fillMaxSize()
.background(Color.LightGray),
scope = scope,
snackbarHostState = snackbarHostState
)
}
}
// in UserInfoScreen.kt
@Composable
fun UserInfoScreen(
scope: CoroutineScope,
snackbarHostState: SnackbarHostState
) {
Column(
modifier = Modifier.fillMaxSize()
) {
SampleContent(
text = "UserInfoScreen",
modifier = Modifier
.fillMaxSize()
.background(Color.LightGray),
scope = scope,
snackbarHostState = snackbarHostState
)
}
}
3개의 컴포저블 함수를 각각 별도의 파일로 만들어두었다. SampleContent()는 MainActivity.kt에 정의해두었던 컴포저블 함수다.
#2-3 NavHost 클래스 구현 및 Scaffold의 content 영역에 두기
...
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
NutricapturenewTheme {
// Navigation 관리의 주체
val navController = rememberNavController()
// Snackbar를 위한 CoroutineScope와 State
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
...
) { innerPadding ->
NavHost(
navController = navController,
startDestination = "nutrientInputScreen",
modifier = Modifier.padding(innerPadding)
) {
composable(route = "nutrientInputScreen") {
NutrientInputScreen(
scope = scope,
snackbarHostState = snackbarHostState
)
}
composable(route = "statisticsScreen") {
StatisticsScreen(
scope = scope,
snackbarHostState = snackbarHostState
)
}
composable(route = "userInfoScreen") {
UserInfoScreen(
scope = scope,
snackbarHostState = snackbarHostState
)
}
}
}
}
}
}
}
@Composable
fun SampleContent( ... ) { ... }
content 영역에 있던 SampleContent()를 제거하고, 그 대신 NavHost()를 위치시켰다. NavHost가 innerPadding을 고려하게 두었고, 3개의 Destination에 각각에 CoroutineScope 및 SnackbarHostState를 전달(생성자 주입)한다.
#3 요약
Destination용 컴포저블 함수를 3개와 NavHost를 만들었다.
#4 완성된 앱
#4-1 스크린샷
가운데에 있는 버튼의 텍스트만 제외하고 이전 게시글과 동일한 스크린샷이 나온다. 내부 구조만 변한 것이다.
#4-2 이 게시글 시점의 Commit
#4-3 본 프로젝트의 가장 최신 Commit
'App 개발 일지 > Nutri Capture' 카테고리의 다른 글
Nutri Capture 방향성 - 고유인지감각, 새 UI 스케치 (4) | 2024.10.03 |
---|---|
Nutri Capture 프론트엔드 - NavigationBar (1) | 2024.09.28 |
Nutri Capture 프론트엔드 - Scaffold (0) | 2024.09.25 |
Nutri Capture 방향성 - 살아남는 앱이 되려면 (0) | 2024.09.22 |
Nutri Capture 방향성 - UI 스케치 (0) | 2023.12.23 |