Android Navigate with arguments in Jetpack Compose

This post is about how to pass arguments/data between composable destinations and add optional arguments using Navigation compose.

Let’s understand how to pass data between composable destinations and add optional arguments with the help of examples.

Creating New Project

1 . Create a new project by going to File ⇒ New Android Project, select Empty Compose Activity, provide app name and then finally click on finish.

2 . Open app-level build.gradle file and under the dependencies section add the below library and then sync the project:

build.gradle

dependencies {
//navigation with compose
implementation("androidx.navigation:navigation-compose:2.4.2")
}

Get the latest navigation-compose dependency from here.

3. Passing data from First Screen composable to Second Screen composable.

@Composable
fun FirstScreen(navController: NavController) {
Button(
onClick = {
// this will navigate to second screen
navController.navigate("second_screen/Second Screen")
}
)
{
Text(text = "Go to Second Screen", fontSize = 25.sp)
}
}

4. Retrieving data passed from First Screen composable in the composable() function of route second_screen and pass it as a parameter to Second Screen composable.

@Composable
fun MainScreen() {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "first_screen"
) {
composable("first_screen") {
FirstScreen(navController = navController)
}
/*
//By default, all arguments are parsed as strings.
composable(
"second_screen/{title}"
) {
SecondScreen(navController = navController, it.arguments?.getString("title"))
}*/
//OR
//You can specify another type by using the arguments parameter to set a type.
composable(
"second_screen/{title}",
arguments = listOf(navArgument("title")
{
type = NavType.StringType
})
) {
SecondScreen(navController = navController, it.arguments?.getString("title"))
}
}
}

5. Using data passed as a parameter to Second Screen composable.

@Composable
fun SecondScreen(navController: NavController, title: String?) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = title.toString(),
fontSize = 40.sp,
color = Color.Magenta,
fontWeight = FontWeight.Bold
)
Button(
onClick = {
// this will navigate to first screen
navController.navigate("first_screen")
}
)
{
Text(text = "Go to First Screen", fontSize = 25.sp)
}
}
}

Complete MainActivity code

6. The below MainActivity file shows you how to pass string data from the First screen composable to the Second screen composable using Navigation compose.

MainActivity.kt

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposePassArgumentExpTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainScreen()
}
}
}
}
}

@Composable
fun MainScreen() {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "first_screen"
) {
composable("first_screen") {
FirstScreen(navController = navController)
}
composable(
"second_screen/{title}",
arguments = listOf(navArgument("title")
{
type = NavType.StringType
})
) {
SecondScreen(navController = navController, it.arguments?.getString("title"))
}
}
}


@Composable
fun FirstScreen(navController: NavController) {

Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "First Screen",
fontSize = 40.sp,
color = Color.Blue,
fontWeight = FontWeight.Bold
)

Button(
shape = RoundedCornerShape(8.dp),
modifier = Modifier.padding(all = Dp(8F)),
onClick = {
// this will navigate to second screen
navController.navigate("second_screen/Second Screen")
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Blue,
contentColor = Color.White
)
)
{
Text(text = "Go to Second Screen", fontSize = 25.sp)
}

}
}

@Composable
fun SecondScreen(navController: NavController, title: String?) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = title.toString(),
fontSize = 40.sp,
color = Color.Magenta,
fontWeight = FontWeight.Bold
)

Button(
shape = RoundedCornerShape(8.dp),
modifier = Modifier.padding(all = Dp(8F)),
onClick = {
// this will navigate to first screen
navController.navigate("first_screen")
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Magenta,
contentColor = Color.White
)
)
{
Text(text = "Go to First Screen", fontSize = 25.sp)
}
}
}

Adding optional arguments

Navigation Compose also supports optional navigation arguments. Optional arguments differ from required arguments in two ways:

  • They must be included using query parameter syntax (“?argName={argName}”)
  • They must have a defaultValue set, or have nullability = true (which implicitly sets the default value to null)

7. Passing optional data from First Screen composable to Second Screen composable.

@Composable
fun FirstScreen(navController: NavController) {
Button(
onClick = {
// this will navigate to second screen
navController.navigate("second_screen?title = Second Screen")
}
)
{
Text(text = "Go to Second Screen", fontSize = 25.sp)
}
}

8. Retrieving optional data passed from First Screen composable in the composable() function of route second_screen and pass it as a parameter to Second Screen composable. You must have some default value, in case, if there is no argument passed to the destination, the defaultValue of “Second Screen” will be used instead.

@Composable
fun MainScreen() {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "first_screen"
) {
composable("first_screen") {
FirstScreen(navController = navController)
}

composable(
"second_screen?title={title}",
arguments = listOf(navArgument("title")
{
type = NavType.StringType
defaultValue = "Second Screen"
})
) {
SecondScreen(navController = navController, it.arguments?.getString("title"))
}
}
}

Complete MainActivity code

9. The below MainActivity file shows you how to pass optional string data from the First screen composable to the Second screen composable using Navigation compose.

MainActivity.kt

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposePassArgumentExpTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainScreen()
}
}
}
}
}

@Composable
fun MainScreen() {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "first_screen"
) {
composable("first_screen") {
FirstScreen(navController = navController)
}
composable(
"second_screen?title={title}",
arguments = listOf(navArgument("title")
{
type = NavType.StringType
defaultValue = "Second Screen"
})
) {

SecondScreen(navController = navController, it.arguments?.getString("title"))
}
}
}


@Composable
fun FirstScreen(navController: NavController) {

Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "First Screen",
fontSize = 40.sp,
color = Color.Blue,
fontWeight = FontWeight.Bold
)

Button(
shape = RoundedCornerShape(8.dp),
modifier = Modifier.padding(all = Dp(8F)),
onClick = {
// this will navigate to second screen
navController.navigate("second_screen?title = Second Screen")
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Blue,
contentColor = Color.White
)
)
{
Text(text = "Go to Second Screen", fontSize = 25.sp)
}

}
}

@Composable
fun SecondScreen(navController: NavController, title: String?) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = title.toString(),
fontSize = 40.sp,
color = Color.Magenta,
fontWeight = FontWeight.Bold
)

Button(
shape = RoundedCornerShape(8.dp),
modifier = Modifier.padding(all = Dp(8F)),
onClick = {
// this will navigate to first screen
navController.navigate("first_screen")
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Magenta,
contentColor = Color.White
)
)
{
Text(text = "Go to First Screen", fontSize = 25.sp)
}
}
}

When you run the app it will look like this:

     

 

 

 

Leave a Reply