val nav_version = "2.7.6"
implementation("androidx.navigation:navigation-compose:$nav_version")
일단 라이브러리를 추가해준다.
setContent {
val navController = rememberNavController()
}
...
@Composable
fun FirstScreen(){
}
@Composable
fun SecondScreen(){
}
@Composable
fun ThirdScreen(){
}
전환할 화면들을 만들어 주고 네비를 관리할 navController를 만들어준다
문제가 생겼는데
setContent {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "first"){
composable("first"){
FirstScreen()
}
}
하면 기존에 가능했지만
2.7.6 버전에 들어오면서 NavHost안에 startDestination이 없어졌다.
버전이 바뀌면서 방식이 변경된거 같다
그럼 뭐 뜯어봐야지
위에 주석으로 설명한 부분을 보면 graph가 destination을 관리하는 부분일것 같다.
NavGraph를 들어가보면
NavGraph는 ID별로 가져올 수 있는 [NavDestination] 노드의 모음이라고 되어있다.
그럼 NavDestination을 들어가보면
전체 탐색 그래프 내의 하나의 노드를 나타냈고
Navigator.createDestination를 통해 생성된다고 되어있다.
네비게이터는 이미 만들었다
val navController = rememberNavController()
...
public fun rememberNavController(
vararg navigators: Navigator<out NavDestination>
): NavHostController {
rememberNavController를 보면 Navigator인걸 확인 할 수 있는데
그럼 이걸로 NavDestination을 만들어보자
navController.을 쳐보면 누가봐도 써야할것 같은 createGraph가 보인다
setContent {
val navController = rememberNavController()
val navGraph = navController.createGraph(startDestination = "first"){
composable("first") {
FirstScreen ()
}
composable("second") {
SecondScreen ()
}
composable("third") {
ThirdScreen()
}
}
NavHost(navController = navController, graph = navGraph)
}
NavHost에 있던 builder부분도 Destination관리를 Graph에서 하니 자연스럽게 Graph로 옮겨가서
Graph에 람다로 composable을 설정해주고
NavHost에 컨트롤러와 함께 넣어준다.
이제 화면에 표시할 스크린을 만들어주자
@Composable
fun FirstScreen(
onClick: (Int , String?) -> Unit
) {
val (value , setValue) = remember {
mutableStateOf("")
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "첫화면")
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { onClick(2, null) }) {
Text(text = "두번째")
}
Spacer(modifier = Modifier.height(16.dp))
TextField(value = value, onValueChange = setValue)
Button(onClick = { onClick(3, value) }) {
Text(text = "세번째")
}
}
}
@Composable
fun SecondScreen(
onClick: (Int) -> Unit
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "두번째 화면")
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { onClick(1) }) {
Text(text = "뒤로")
}
}
}
@Composable
fun ThirdScreen(value: String,
onClick: (Int) -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(text = "세번째 화면")
Spacer(modifier = Modifier.height(16.dp))
Text(text = "$value")
Button(onClick = { onClick(1) }) {
Text(text = "뒤로")
}
}
}
버튼으로 이동하게 구성했고 첫번째 화면에서 세번째 화면으로 이동할때 텍스트 필드의 값을 넘겨 줄 거다
setContent {
val navController = rememberNavController()
val navGraph = navController.createGraph(startDestination = "first"){
composable("first") {
FirstScreen { int, value ->
when (int) {
2 -> navController.navigate("second")
3 -> navController.navigate("third/$value")
else -> Log.e("main", "unknown: $int, $value")
}
}
}
composable("second") {
SecondScreen { navController.navigate("first") }
}
composable("third/{value}") {backStackEntry ->
ThirdScreen( value = backStackEntry.arguments?.getString("value") ?: "") { navController.navigate("first") }
}
}
NavHost(navController = navController, graph = navGraph)
}
콜백으로 받아 몇번째로 이동하는지 구별하고
third/$value로 Url처럼 작성 할 수있다.
받는 부분에선
composable("third/{value}") 넘겨 받을 부분을 중괄호로 감싸준다.
그리고 composable을 열어보면
public fun NavGraphBuilder.composable(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
...
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit
) {
...
public class NavBackStackEntry private constructor(
private val context: Context?,
콜백에서 NavBackStackEntry객체가 있는데 Context를 받는다 이걸 이용해서
backStackEntry.arguments?.getString("value") ?: ""
이렇게 번들을 얻을 수 있다.