네비게이션을 사용하기 위해선 디팬던시 필요
Kotlin 1.8.22 버전에 사용할 수 있는 navigation 버전은 2.5.3
implementation 'androidx.navigation:navigation-compose:2.5.3'
탐색 컨트롤러를 만든다. 탐색 그래프를 보유하고 앱이 그래프(NavHost)의 대상 간에 이동할 수 있는 메서드를 노출한다.
사용자가 방문한 대상을 추적하고 화면을 이동할 수 있도록 허용한다.
앱 화면을 만드는 백 스택과 각 화면의 상태를 유지한다.
@Composable
fun myApp() {
//NavController는 중심이 되는 API다
//앱 화면을 만드는 백 스택과 각 화면의 상태를 유지함
val navController = rememberNavController()
}
NavHost를 사용하기 위해선 NavController가 필요하다.
이 NavController를 NavHost에 전달할 수 있는데 startDestination을 정의해야한다.
startDestination?
어떤 컴포저블이, 즉 어느 화면이 시작 화면인가 지정하는 것
예시
//startDestination에 시작화면 지정
NavHost(navController = navController, startDestination = Profile) {
composable<Profile> { ProfileScreen( /* ... */ ) } //개별 화면인 다른 컴포저블을 여기에 지정한다
composable<FriendsList> { FriendsListScreen( /* ... */ ) }
// Add more destinations similarly.
}
NavController과 NavHost를 이용 하여 화면간 이동이 가능하도록 연동한다.
NavHost에 rememberNavController()와 기준이 될 화면을 매개변수로 둔다
NavHost함수 안에서 composable을 통해 화면을 식별할 경로 이름을 지정하고 만들어둔 화면과 연동한뒤 navController.navigate를 통해 이동할 화면의 식별이름을 쓴다.
MainActivity.kt
package com.lullulalal.navigationsample
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavigationSampleTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
myApp()
}
}
}
}
}
@Composable
fun myApp() {
//NavController는 중심이 되는 API다
//앱 화면을 만드는 백 스택과 각 화면의 상태를 유지함
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "firstScreen") {
//composable => 경로와 필요한 경우 인수들을 갖을 수 있다
//route는 앱 어디서든 화면을 식별하는데 사용함
composable(route = "firstScreen"){
//firstScreen을 경로로 하는 컴포저블이 실행될 때 무슨 일이 일어나야 하는지 정의
FirstScreen {
navController.navigate("secondScreen")
}
}
composable(route = "secondScreen"){
SecondScreen{
navController.navigate("thirdScreen")
}
}
composable("thirdScreen") {
ThirdScreen {
navController.navigate("firstScreen")
}
}
}
}
버튼을 이용해 화면을 이동하기 위해선 두가지 준비가 필요하다
1.실행할 코드나 함수를 전달하는 것, 익명 함수 또는 람다 사용해 간결하게 할 수 있음
fun FirstScreen(navigationToSecondScreen:()->Unit)
2.버튼 안에서 매개변수로 받은 함수 호출
4-1) 첫번쨰 화면
package com.lullulalal.navigationsample
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
// 버튼을 이용해 화면을 이동하기 위해선 두가지 준비가 필요하다
//1.실행할 코드나 함수를 전달하는 것, 익명 함수 또는 람다 사용해 간결하게 할 수 있음
//fun FirstScreen(navigationToSecondScreen:()->Unit)
//2.버튼 안에서 매개변수로 받은 함수 호출
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FirstScreen(navigationToSecondScreen:()->Unit) {
val name = remember {
mutableStateOf("")
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "First", fontSize = 24.sp)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(value = name.value, onValueChange = {
name.value = it
})
Button(onClick = {
navigationToSecondScreen()
}) {
Text(text = "이동")
}
}
}
@Preview(showBackground = true)
@Composable
fun FirstScreenPreview() {
NavigationSampleTheme {
FirstScreen({})
}
}
4-2) 두번째 화면
package com.lullulalal.navigationsample
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
@Composable
fun SecondScreen(navigateToThirdScreen:()->Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Second", fontSize = 24.sp)
Text(text = "hihi~", fontSize = 24.sp)
Button(onClick = {
navigateToThirdScreen()
}) {
Text(text = "Go to Third Screen")
}
}
}
@Preview(showBackground = true)
@Composable
fun SecondScreenPreview() {
NavigationSampleTheme {
SecondScreen({})
}
}
4-3) 세번째 화면
package com.lullulalal.navigationsample
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
@Composable
fun ThirdScreen(navigationToFirstScreen:()->Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "This is the Third Screen. Go to First Screen", fontSize = 24.sp)
Text(text = "나는 세번째 화면", fontSize = 24.sp)
Button(onClick = {
navigationToFirstScreen()
}) {
Text(text = "first로 이동")
}
}
}
@Preview(showBackground = true)
@Composable
fun ThirdScreenPreview() {
NavigationSampleTheme {
ThirdScreen({})
}
}
A화면에서 B화면으로 데이터 주고 B화면에서 받은 데이터를 다시 A화면으로 돌려주기
package com.lullulalal.navigationsample
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
@Composable
//fun SecondScreen(name:String, navigateToThirdScreen:(nameToFirst)->Unit) {
fun SecondScreen(name:String, navigationToFirstScreen:()->Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Second", fontSize = 24.sp)
Text(text = "welcome $name", fontSize = 24.sp)
Button(onClick = {
// navigateToThirdScreen()
navigationToFirstScreen()
}) {
Text(text = "Go to Third Screen")
}
}
}
@Preview(showBackground = true)
@Composable
fun SecondScreenPreview() {
NavigationSampleTheme {
SecondScreen("Rose",{})
}
}
2-1) navigationToSecondScreen() -> Unit에 빈값을 보내고 있었는데
매개변수로 1에게 넘겨줄 데이터의 자료형 쓰기
fun FirstScreen(navigationToSecondScreen:(String)->Unit) {...}
2-2) navigationToSecondScreen호출하는 곳에서 넘겨줄 데이터 매개변수로 넣기
navigationToSecondScreen(name.value)
package com.lullulalal.navigationsample
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
// 버튼을 이용해 화면을 이동하기 위해선 두가지 준비가 필요하다
//1.실행할 코드나 함수를 전달하는 것, 익명 함수 또는 람다 사용해 간결하게 할 수 있음
//fun FirstScreen(navigationToSecondScreen:()->Unit)
//2.버튼 안에서 매개변수로 받은 함수 호출
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FirstScreen(navigationToSecondScreen:(String)->Unit) {
val name = remember {
mutableStateOf("")
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "First", fontSize = 24.sp)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(value = name.value, onValueChange = {
name.value = it
})
Button(onClick = {
navigationToSecondScreen(name.value)
}) {
Text(text = "이동")
}
}
}
@Preview(showBackground = true)
@Composable
fun FirstScreenPreview() {
NavigationSampleTheme {
FirstScreen({})
}
}
package com.lullulalal.navigationsample
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.lullulalal.navigationsample.ui.theme.NavigationSampleTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavigationSampleTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
myApp()
}
}
}
}
}
@Composable
fun myApp() {
//NavController는 중심이 되는 API다
//앱 화면을 만드는 백 스택과 각 화면의 상태를 유지함
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "firstScreen") {
//composable => 경로와 필요한 경우 인수들을 갖을 수 있다
//route는 앱 어디서든 화면을 식별하는데 사용함
composable(route = "firstScreen"){
//firstScreen을 경로로 하는 컴포저블이 실행될 때 무슨 일이 일어나야 하는지 정의
FirstScreen {name, age->
navController.navigate("secondScreen/$name/$age") //경로에 데이터
}
}
composable(route = "secondScreen/{name}/{age}"){
val name = it.arguments?.getString("name") ?: "no data"
val age = it.arguments?.getString("age") ?: "no age"
//첫번째 화면에서 아무것도 입력하지않고 버튼 클릭하면 no data 나옴
SecondScreen(name,age){
// navController.navigate("thirdScreen")
navController.navigate("firstScreen")
}
}
// composable("thirdScreen") {
// ThirdScreen {
// navController.navigate("firstScreen")
// }
// }
}
}
참고 사이트)
https://developer.android.com/develop/ui/compose/navigation?hl=ko