Jetpack Compose ๊ฒ์๊ธ ์๋ฆฌ์ฆ
- ๊ธฐ์ด
- Surface
- Modifier
- Layout, Arrangement, Alignment
- Button
- Lazy Column
- State ๊ธฐ์ด
- State Remembering
- State Hoisting
- ViewModel์์ State ์ฌ์ฉํ๊ธฐ
- StateFlow์ SharedFlow
- Scaffold
- Side-effects
- ๊ฐ์ฒด ์งํฅ์ UI ๋ ์ด์ด ์ค๊ณ
- Navigation ๊ธฐ์ด
- Navigation์ Destination ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ (NavBackStackEntry.arguments)
#1 ๊ฐ์
#1-1 ์ ํต์ ์ธ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Navigation
[Android] Navigation - ๊ธฐ์ด
#1 ์ด์ ๊ธ [Android] Navigation - ํ๊ฒฝ ์ค์ #1 Navigation#1-1 ์กํฐ๋นํฐ ๋ฐ ํ๋๊ทธ๋จผํธ ๊ตฌ์ฑ์ ํธ๋ ๋์์ฆ ์๋๋ก์ด๋ ๊ฐ๋ฐ์ ํธ๋ ๋๋ ํ๋์ ์กํฐ๋นํฐ, ์ฌ๋ฌ ๊ฐ์ ํ๋๊ทธ๋จผํธ๋ค. ์ด๋ ๊ตฌ๊ธ์ ๊ถ์ฅ์ฌํญ
kenel.tistory.com
์ ๊ฒ์๊ธ์ Jetpack Compose๊ฐ ์ฐ์ด์ง ์์ ์ ํต์ ์ธ ๊ตฌ์กฐ์ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Navigation์ ๋ํด ๋ค๋ฃฌ ๊ฒ์๊ธ์ด๋ค.
#1-2 Jetpack Compose ๊ตฌ์กฐ์ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Navigation
Compose๋ฅผ ์ฌ์ฉํ ํ์ | Jetpack Compose | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. Compose๋ฅผ ์ฌ์ฉํ ํ์ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. ํ์ ๊ตฌ์ฑ์์๋ Jetpack ์ง์์ ์
developer.android.com
๋ณธ ๊ฒ์๊ธ์ Jetpack Compose ๊ตฌ์กฐ์์ ์ฌ์ฉ ๊ฐ๋ฅํ Navigation์ ๋ํด ๋ค๋ค๋ณธ๋ค. #1-1๊ณผ ํ๋ ๋์์ ๋์ผํ์ง๋ง, ๊ตฌํ ๋ฐฉ๋ฒ์ ๊ฝค ๋ค๋ฅด๋ค.
#2 ๊ธฐ์
#2-1 ๊ฐ์
NavHost ๊ฐ์ฒด๊ฐ ํ๋ฉด ์ ํ์ ์ฃผ๊ดํ๋ค. ํ๋ฉด ์ ํ์ ํธ๋ฆฌ๊ฑฐ(๋ฐ์)์ํค๋ ๊ฐ์ฒด๋ NavHostController๋ก, ๋ง์น TV ๋ฆฌ๋ชจ์ฝ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค. NavHost์ ์ํด ๊ด๋ฆฌ๋ ๊ฐ๊ฐ์ ํ๋ฉด ์ปดํฌ์ ๋ธ์ Destination(๋ชฉ์ ์ง)์ด๋ผ ํ๋ฉฐ, ๊ทธ Destination์ route๋ผ๋ Stringํ ์ธ์๋ฅผ ๊ฐ์ง๋ค. ์ด route๋ ๊ฐ Destination์ ์๋ณ(๊ตฌ๋ถ)ํ๋๋ฐ ์ฌ์ฉ๋๋ค. ๋ฐ๋ผ์, ๊ฐ์ NavHost ๋ด์์ route์ ์ด๋ฆ์ ์ค๋ณต๋จ ์์ด ๊ณ ์ (unique)ํด์ผ ํ๋ค.
#2-2 ๋์๋

์์ ํ์์ผ๋ก ๊ทธ๋ฆฐ ๋์๋๋ค. #3์์ ์ค์ ์ฝ๋๋ก ๊ตฌํํ๋ค.
#2-3 NavHost
@Composable
public fun NavHost(
navController: NavHostController,
startDestination: String,
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
route: String? = null,
enterTransition: @JvmSuppressWildcards() (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) = { fadeIn(animationSpec = tween(700)) },
exitTransition: @JvmSuppressWildcards() (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition) = { fadeOut(animationSpec = tween(700)) },
popEnterTransition: @JvmSuppressWildcards() (AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition) = enterTransition,
popExitTransition: @JvmSuppressWildcards() (AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition) = exitTransition,
sizeTransform: @JvmSuppressWildcards() (AnimatedContentTransitionScope<NavBackStackEntry>.() -> SizeTransform?)? = null,
builder: NavGraphBuilder.() -> Unit
): Unit
Navigation ๋์์ ์ฃผ๊ดํ๋ ๊ฐ์ฒด๋ NavHost๋ผ๋ @Composable ํจ์๋ค. ์ด์ ๊ฒ์๊ธ(#1-1)์์๋ Activity ๋๋ Fragment์ ์ ํ์ ์ํด Navigation graph๋ผ๋ ์ผ์ข ์ ์ง๋๋ฅผ ์ฌ์ฉํ์๋ค. Jetpack Compose์ Navigation์์ Navigation graph์ ์ญํ ์ ์ํํ๋ ๊ฒ์ด ๋ฐ๋ก NavHost๋ค.
๊ฐ ์ธ์์ ๋ํ ์ค๋ช ์ ์๋์ ๊ฐ๋ค.
navController: NavHostController
NavHost๊ฐ ์ง๋๋ผ๋ฉด, NavHostController๋ ์๊ฐ์ด๋ ์ฅ์น๋ค. ์ง๋ ์์์ ๊ฐ๊ณ ์ถ์ ๋ชฉ์ ์ง(route)๋ฅผ ์ ํํ์ฌ ์ด๋ํ ์ ์๋ค. ํ๋ฉด ๊ฐ์ ์ ํ์ ํธ๋ฆฌ๊ฑฐ(๋ฐ์)์ํค๊ธฐ ์ํด์๋ NavHostController๋ฅผ ์ฌ์ฉํ๋ค. TV ๋ฆฌ๋ชจ์ฝํ๊ณ ๋น์ทํ๋ค.
startDestination: String
๋ด๋น๊ฒ์ด์
๊ทธ๋ํ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์๋ ํ์ ์ปดํฌ์ ๋ธ์ด๋ค. NavHost๋ Composable ํจ์์ง๋ง, ๋์ ๋ณด์ด์ง ์๋๋ค. ์๊ธฐ ์์ ๋์ startDestination์ผ๋ก ์ง์ ๋ ํ์ ์ปดํฌ์ ๋ธ์ ํ์ํ๋ค.
route: String?
NavHost์ ์๋ณ์. ํ๋์ NavHost๊ฐ ๊ฐ์ง๊ณ ์๋ ํ์ ์ปดํฌ์ ๋ธ์ธ ๋ชฉ์ ์ง(Destination)์ ์๋ณ์(route)ํ๊ณ ๋ ๋ค๋ฅธ ๊ฐ๋
์ด๋ค. ์ฑ ๋ด์์ NavHost๊ฐ ์ฌ๋ฌ ๊ฐ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋๋ ์ธ์๋ค. ๊ธฐ๋ณธ๊ฐ์ null๋ก ์ง์ ๋์ด์๋ค.
@JvmSuppressWildcards()
์๋ฐ์์ ํธํ์ฑ์ ์ํด ์ฌ์ฉ๋๋ ์ด๋
ธํ
์ด์
. ์ด ์ด๋
ธํ
์ด์
์ ์๋ตํ๋ฉด NavHost๋ฅผ ์๋ฐ ํ๊ฒฝ์์ ์ฌ์ฉํ ๋, ์ธ์ ๋ฐ์ดํฐํ์ "? super" ๋ฐ "? extends" ๋ฑ์ ์์ผ๋์นด๋("?") ๊ตฌ๋ฌธ์ด ์ถ๊ฐ๋์ด ์ฝ๋๊ฐ ๋๋ฌ์์ง๋ค๊ณ ํ๋ค.
enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition
๋ค๋ฅธ Destination์ด ์ข
๋ฃ๋๋ฉฐ ํ์ฌ Destination๋ก ์ ํํ์ ๋ ๋์ค๋ ์ ๋๋ฉ์ด์
.
(์ฐธ์กฐ: ์ ํต์ ์ธ ๊ตฌ์กฐ์์์ Navigation ์ ๋๋ฉ์ด์
์ enterTransition)
exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition
ํ์ฌ Destination์ด ์ข
๋ฃ๋ ๋ ๋ค๋ฅธ Destination์ผ๋ก ์ ํ๋๋ฉฐ ๋์ค๋ ์ ๋๋ฉ์ด์
.
(์ฐธ์กฐ: ์ ํต์ ์ธ ๊ตฌ์กฐ์์์ Navigation ์ ๋๋ฉ์ด์
์ exitTransition)
popEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition
(์ฌ์ฉ์์ ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ ํด๋ฆญ์ผ๋ก ์ธํด) ์ด์ Destination์ด ์ข
๋ฃ๋๋ฉฐ ํ์ฌ Destination๋ก ์ ํํ์ ๋ ๋์ค๋ ์ ๋๋ฉ์ด์
.
(์ฐธ์กฐ: ์ ํต์ ์ธ ๊ตฌ์กฐ์์์ Navigation ์ ๋๋ฉ์ด์
์ popEnterTransition)
popExitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition
(์ฌ์ฉ์์ ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ ํด๋ฆญ์ผ๋ก ์ธํด) ํ์ฌ Destination์ด ์ข ๋ฃ๋ ๋ ๋ค๋ฅธ Destination์ผ๋ก ์ ํ๋๋ฉฐ ๋์ค๋ ์ ๋๋ฉ์ด์ .
(์ฐธ์กฐ: ์ ํต์ ์ธ ๊ตฌ์กฐ์์์ Navigation ์ ๋๋ฉ์ด์
์ popExitTransition)
sizeTransform: (AnimatedContentTransitionScope<NavBackStackEntry>.() -> SizeTransform?)?
ํ๋ฉด ์ ํ ์ ํฌ๊ธฐ๊ฐ ๋ณ๊ฒฝ๋๋ ์ ๋๋ฉ์ด์
์ ์ถ๊ฐํ๋ค. ๊ธฐ๋ณธ๊ฐ์ null์ด๋ค.
builder: NavGraphBuilder.() -> Unit
NavHost๊ฐ ๊ฐ์ง Destination๋ค์ ์ ์.
#2-4 builder: NavGraphBuilder.() -> Unit
public fun NavGraphBuilder.composable(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(),
content: @Composable (NavBackStackEntry) -> Unit
): Unit
NavHost์ ์ ์๋ ๋ง์ง๋ง ์ธ์์ด๋ฉฐ, NavHost๊ฐ ๋ณด์ ํ๋ Destination์ ์ ์ฒด์ด๊ธฐ๋ ํ๋ค.
๊ฐ ์ธ์์ ๋ํ ์ค๋ช ์ ์๋์ ๊ฐ๋ค.
route: String
Destination๋ผ๋ฆฌ ์๋ณํ๊ธฐ ์ํ ์ด๋ฆ.
arguments: List<NamedNavArgument>
Destination ๊ฐ ์ ๋ฌํ ๋ฐ์ดํฐ์ ๋ฆฌ์คํธ. ํ๋ฉด ์ ํ ์์ ๋ฐ์ดํฐ ์ ๋ฌ์ด ๋ชฉ์ ์ด๋ค. ๋ง์น ์น ํ๋ก๊ทธ๋๋ฐ์์ URL์ ๋ฐ์ดํฐ๋ฅผ ์ค์ด๋ณด๋ด๋ ๊ฒ(GET ์์ฒญ)๊ณผ ๋น์ทํ๊ฒ, route์ ์ด arguments๋ฅผ ๋ฃ์ด ์ค์ด๋ณด๋ธ๋ค. ์ด์ด์ง๋ ๊ธ(#8)์์ ์์ธํ ๋ค๋ฃฌ๋ค.
deepLinks: List<NavDeepLink>
ํด๋น Destination์ ์ง์
ํ ์ ์๋ ๋ฅ ๋งํฌ๋ค์ ๋ฆฌ์คํธ. ๋ฅ ๋งํฌ๋ ์ฑ ์ธ๋ถ(์น ๋ธ๋ผ์ฐ์ , QR ์ฝ๋, ํ ์ฑ)์์ ํน์ Destination์ผ๋ก ๋ฐ๋ก ์ ๊ทผํ ์ ์๋ ๋งํฌ๋ฅผ ๋งํ๋ค๊ณ ํ๋ค. ๋ณธ ๊ฒ์๊ธ์์ ๋ค๋ฃจ์ง ์๋๋ค.
content: @Composable (NavBackStackEntry) -> Unit
Destination์ ํด๋นํ๋ ์ปดํฌ์ ๋ธ ํจ์. NavBackStackEntry๋ Destination์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด๋ก, arguments์ ์ ์ฅํ ๋ฐ์ดํฐ์ ์ ๊ทผํ๊ธฐ ์ํ ํต๋ก๋ก ์ฌ์ฉ๋๋ค (์ด์ด์ง๋ ๊ธ(#8) ์ฐธ์กฐ).
#3 ๊ตฌํ
#3-1 ๋ชจ๋ ์์ค build.gradle.kt
plugins {
...
}
android {
...
}
dependencies {
...
// Navigation
implementation("androidx.navigation:navigation-runtime-ktx:2.8.0")
implementation("androidx.navigation:navigation-compose:2.8.0")
}
#3-2 NavHost
// package com.example.navigationbasics
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
@Composable
fun MyNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = "firstScreen"
) {
// (1) FirstScreen
composable(route = "firstScreen") {
FirstScreen(navController)
}
// (2) SecondScreen
composable(route = "secondScreen") {
SecondScreen(navController)
}
}
}
MyNavHost๋ Activity์ setContent { ... }์ ๋ฃ์ ์ปดํฌ์ ๋ธ์ด๋ค (#3-5 ์ฐธ์กฐ). ์ ์ฝ๋์์ MyNavHost ๋ฐ NavHost์ modifier๋ฅผ ํ์ ์ปดํฌ์ ๋ธ์ธ FirstScreen ๋ฐ SecondScreen์ ์ ๋ฌํ๊ณ ์์ง ์์ผ๋ฏ๋ก, ๊ทธ ์กด์ฌ๊ฐ ๋ฌด์๋ฏธํ๋ค. ์ญ์ ํ๋ ํธ์ด ๋ ๊น๋ํ ์ฝ๋๊ฒ ์ง๋ง, Activity๋ก๋ถํฐ Modifier๋ฅผ ์ด์ด๋ฐ์ NavHost๋ฅผ ๊ฑฐ์ณ Destination๊น์ง ์ ๋ฌ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฑธ ๋ณด์ด๊ณ ์ถ๊ธฐ์ ๊ทธ๋ฅ ๋ ๋๊ฒ ๋ค.
#3-3 ์ฒซ๋ฒ์งธ Destination (FirstScreen)
// package com.example.navigationbasics
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
@Composable
fun FirstScreen(navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "First Screen")
Button(
onClick = { navController.navigate("secondScreen") }
) {
Text(text = "Go to Second Screen")
}
}
}
NavHostController๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง ํ์ธํ ์ ์๋ค.
#3-4 ๋๋ฒ์งธ Destination (SecondScreen)
// package com.example.navigationbasics
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
@Composable
fun SecondScreen(navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "Second Screen")
Button(
onClick = { navController.navigate("firstScreen") }
) {
Text(text = "Go to First Screen")
}
}
}
#3-3๊ณผ ๊ฐ์ ๋งฅ๋ฝ์ ์ฝ๋๋ค.
#3-5 Activity
// package com.example.navigationbasics
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier
import com.example.navigationbasics.ui.theme.NavigationBasicsTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
NavigationBasicsTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
MyNavHost(modifier = Modifier.padding(innerPadding))
}
}
}
}
}
MyNavHost๋ ์ปดํฌ์ ๋ธ์ด์ง๋ง ํํ๊ฐ ์๋ค. ๋์ , NavHost()์ ์ธ์ ์ค ํ๋์ธ startDestination์ ์ ํ Destination์ ๋์ ๋ณด์ฌ์ค๋ค.
#4 ์๋ ํ์ธ

#5 ์ฝ๋ ๋ฆฌํฉํ ๋ง: ๋จ์ผ ์ง์ค ๊ณต๊ธ์(single source of truth, SSOT) ์์น
#5-1 SSOT ์์น?
๋จ์ผ ์ง์ค ๊ณต๊ธ์ - ์ํค๋ฐฑ๊ณผ, ์ฐ๋ฆฌ ๋ชจ๋์ ๋ฐฑ๊ณผ์ฌ์
์ํค๋ฐฑ๊ณผ, ์ฐ๋ฆฌ ๋ชจ๋์ ๋ฐฑ๊ณผ์ฌ์ .
ko.wikipedia.org
์ ์์น์ ํ ๋ง๋๋ก ์ ์ํ๋ฉด, "๋ฐ์ดํฐ ์กฐ์ ๋์์ ํ ๊ณณ์ผ๋ก ๋ชฝ๋ ๋ชจ์"์ด๋ค. ์ด ์์น์ ๊ธฐ๋ฐํ์ฌ #3์ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํด๋ณธ๋ค.
#5-2 NavHost
// package com.example.navigationbasics
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
@Composable
fun MyNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController()
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = "firstScreen"
) {
// (1) FirstScreen
composable(route = "firstScreen") {
FirstScreen(navigateToSecondScreen = { navController.navigate("secondScreen") })
}
// (2) SecondScreen
composable(route = "secondScreen") {
SecondScreen(navigateToFirstScreen = { navController.navigate("firstScreen") })
}
}
}
FirstScreen ๋ฐ SecondScreen์ NavHostController๋ฅผ ์ฃผ๋ ๋์ , NavHostController์ ํ ๋์(์ด๋ฒคํธ)๋ฅผ ์ฃผ๊ฒ๋ ๋ฐ๊พผ๋ค. ์ฆ, FirstScreen์์ ์กฐ์ํ NavHostController์ ๋์์ ๋ฏธ๋ฆฌ NavHost๋จ์์ ์ ์ํ์ฌ ๋ด๋ ค์ค๋ค. ์ด๋ฅผ SSOT ํจํด์ด๋ผ๊ณ ํ๋ฉฐ, ์ด ํจํด์ ๊ตฌํํจ์ผ๋ก์จ (๊ธฐ์กด ๋๋น ๋ณ์๋ฅผ ๋ณด๋ด์ฃผ์ง ์๋๋ค๋ ์ ์์) ๊ฐ์ฒด ๊ฐ ๊ฒฐํฉ๋๊ฐ ๋ฎ์์ก๋ค.
#5-3 FirstScreen
// package com.example.navigationbasics
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun FirstScreen(navigateToSecondScreen: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "First Screen")
Button(
onClick = { navigateToSecondScreen() }
) {
Text(text = "Go to Second Screen")
}
}
}
Button์ onClick ๋ถ๋ถ์ ์์ ํ๋ค. SecondScreen๋ ์ด์ ๊ฐ์ ๋งฅ๋ฝ์ผ๋ก ๊ณ ์น ์ ์์ผ๋ฏ๋ก ์๋ตํ๋ค.
#6 ์์ฝ
NavHost๋ TV ์ฑ๋ ๋ชฉ๋ก, NavController๋ TV ๋ฆฌ๋ชจ์ฝ์ด๋ค.
#7 ์์ฑ๋ ์ฑ
android-practice/jetpack-compose/NavigationBasics at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
#8 ์ด์ด์ง๋ ๊ธ
#8-1 Destination ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ (NavBackStackEntry.arguments)
[Android] Jetpack Compose - Navigation์ Destination ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ (NavBackStackEntry.arguments)
#1 ์ด์ ๊ธ [Android] Jetpack Compose - Navigation ๊ธฐ์ด#1 ๊ฐ์#1-1 ์ ํต์ ์ธ ์๋๋ก์ด๋ ํ๋ก์ ํธ์์์ Navigation [Android] Navigation - ๊ธฐ์ด#1 ์ด์ ๊ธ [Android] Navigation - ํ๊ฒฝ ์ค์ #1 Navigation#1-1 ์กํฐ๋นํฐ ๋ฐ ํ
kenel.tistory.com
#8-2 NavigationBar
[๊ฒ์๊ธ ์์ฑ ๋ฐ ๋งํฌ ์ถ๊ฐ ์์ ]
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Pointer input - PointerInputChange, PointerEvent (0) | 2025.02.07 |
---|---|
[Android] Jetpack Compose - Navigation์ Destination ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ (NavBackStackEntry. (0) | 2024.09.13 |
[Android] Jetpack Compose - ๊ฐ์ฒด ์งํฅ์ UI ๋ ์ด์ด ์ค๊ณ (0) | 2024.09.11 |
[Android] Jetpack Compose - Side-effects (0) | 2024.09.06 |
[Android] Jetpack Compose - Scaffold (0) | 2024.09.05 |