이 프로젝트는 3개의 목적지 화면(홈, 웰컴, 프로필)으로 구성된다. 홈 화면은 하나의 텍스트 필드를 갖고 있으며 사용자가 이름을 입력한다. 버튼을 클릭하면 웰컴 화면으로 이동하면서 사용자의 이름을 인수로 전달하며, 이 이름은 웰컴 메시지에 표시된다. 웰컴 화면도 하나의 버튼을 포함하며, 이 버튼을 클릭하면서 프로필 화면으로 이동할 수 있다. 이 버튼은 오로지 popUpTo() 내비게이션 옵션 메서드를 실험하기 위한 것이다.
sealed class NavRoutes(val route: String) {
data object Home: NavRoutes("home")
data object Welcome: NavRoutes("welcome")
data object Profile: NavRoutes("profile")
}
@Composable
fun Home(navController: NavHostController) {
var userName by remember {
mutableStateOf("")
}
val onUserNameChange = { text: String ->
userName = text
}
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
CustomTextField(
title = "Enter your name",
textState = userName,
onTextChange = onUserNameChange
)
Spacer(modifier = Modifier.size(30.dp))
Button(
onClick = { }
) {
Text(text = "Register")
}
}
}
}
@Composable
fun CustomTextField(
title: String,
textState: String,
onTextChange: (String) -> Unit
) {
OutlinedTextField(
value = textState,
onValueChange = { onTextChange(it) },
singleLine = true,
label = { Text(title) },
modifier = Modifier.padding(10.dp),
textStyle = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 30.sp
)
)
}
@Composable
fun Welcome(navController: NavHostController) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Welcome", style = MaterialTheme.typography.headlineSmall)
Spacer(modifier = Modifier.size(30.dp))
Button(onClick = {}) {
Text(text = "Set up your Profile")
}
}
}
}
@Composable
fun Profile() {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Profile Screen", style = MaterialTheme.typography.headlineSmall)
}
}
기본 요소가 준비되었으므로 내비게이션 컨트롤러와 내비게이션 호스트 인스턴스를 만든다. MainActivity 파일의 MainScreen 컴포저블을 다음과 같이 수정한다.
@Composable
fun MainScreen() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = NavRoutes.Home.route
) {
composable(NavRoutes.Home.route) {
Home(navController = navController)
}
composable(NavRoutes.Welcome.route) {
Welcome(navController = navController)
}
composable(NavRoutes.Profile.route) {
Profile()
}
}
}
MainScreen 함수는 rememberNavController() 메서드 호출을 통해 내비게이션 컨트롤러 인스턴스를 얻는 것에서 시작한다. NavHost 컴포넌트가 호출되고, 홈 화면을 시작 목적지로 할당한다. composable() 메서드가 호출되고 각 화면에 대한 경로가 추가된다.
내비게이션은 홈 화면과 웰컴 화면의 Button 컴포넌트가 클릭될 때 초기화되어야 한다. 두 컴포저블을 이미 navigate() 메서드를 호출할 내비게이션 컨트롤러에 전달되었다. Button 컴포넌트의 onClick 프로퍼티에 내비게이션 코드를 추가한다.
Button(
onClick = {
navController.navigate(NavRoutes.Welcome.route)
}
) {
Text(text = "Register")
}
위는 Home.kt의 버튼 코드이다.
Button(onClick = {
navController.navigate(NavRoutes.Profile.route)
}) {
Text(text = "Set up your Profile")
}
위는 Welcome.kt의 버튼 코드이다.
NavHost 선언 안의 웰컴 목적지 경로를 확장해서 텍스트 필드에 입력된 사용자 이름이 내비게이션 과정에서 웰컴 화면으로 전달되게 한다. 먼저, Welcome() 함수가 사용자 이름을 받아 화면에 표시하도록 수정한다.
@Composable
fun Welcome(navController: NavHostController, userName: String?) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Welcome, $userName", style = MaterialTheme.typography.headlineSmall)
다음으로는 NavHost에서 Welcome 컴포저블에 유저 이름을 전달할 수 있도록 수정한다.
composable(NavRoutes.Welcome.route + "/{userName}") { backStackEntry ->
val userName = backStackEntry.arguments?.getString("userName")
Welcome(navController = navController, userName)
}
마지막으로 Home에서 Welcome으로 넘어가는 버튼을 클릭할 때 유저의 이름을 넘겨주도록 수정한다.
Button(
onClick = {
navController.navigate(NavRoutes.Welcome.route + "/$userName")
}
) {
Text(text = "Register")
}
앱을 실행시키면 홈 -> 웰컴 -> 프로필 화면으로 이동하는 것을 확인할 수 있다. 프로필 화면에서 홈 화면으로 돌아가기 위해서는 뒤로가기를 두 번 눌러야 하는데 popUpTo() 함수를 통해 프로필 화면에서 뒤로가기 한 번으로 홈 화면으로 이동할 수 있도록 변경할 수 있다.
Button(onClick = {
navController.navigate(NavRoutes.Profile.route) {
popUpTo(NavRoutes.Home.route)
}
}) {
Text(text = "Set up your Profile")
}
Welcome 페이지의 버튼에서 navigate() 함수의 후행 람다에 popUpTo() 코드를 위처럼 추가하면 프로필 화면에서 뒤로가기 한 번으로 홈 화면으로 돌아갈 수 있다.