But, wait... What is navigation?
As the documentation says,
Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app.
In simple words, Navigation helps us to go to different screens simply, and also let us do more complex things, but this time we are going to focus on just navigate between three screens, but using JetPack Compose.
So, let's start!
First, in Android studio we are going to create a new Empty Compose Activity:
Then add three kotlin files. In my case, I like to add a package for each screen, but you can add the files in the same package, it doesn't matter.
So far, our project has a MainActivity.kt and three kotlin files: DetailScreen.kt, HomeScreen.kt and LoginScreen.kt. Also, you can see I added a package called navigation, please add it too, we are going to need it in a moment.
Now, we need to add the following code to the Files we just created:
LoginScreen.kt
@Composable
fun LoginScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.Center
) {
Text(
text = "Login Screen",
fontSize = MaterialTheme.typography.h3.fontSize,
fontWeight = FontWeight.Bold
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.Center
) {
Button(
shape = MaterialTheme.shapes.medium,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Black),
modifier = Modifier.padding(5.dp),
onClick = {
//TODO: Navigate to Home Screen
}
) {
Text(
text = "Go to Home Screen",
modifier = Modifier.padding(5.dp),
style = MaterialTheme.typography.button.copy(
fontWeight = FontWeight.Bold,
color = Color.White
)
)
}
}
}
}
HomeScreen.kt
@Composable
fun HomeScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.Center
){
Text(
text = "Home Screen",
fontSize = MaterialTheme.typography.h3.fontSize,
fontWeight = FontWeight.Bold
)
}
Row( modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.Center
){
Button(
shape = MaterialTheme.shapes.medium,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Black),
modifier = Modifier.padding(5.dp),
onClick = {
//TODO: Navigate to Details
}
) {
Text(
text = "Go to Details",
modifier = Modifier.padding(5.dp),
style = MaterialTheme.typography.button.copy(
fontWeight = FontWeight.Bold,
color = Color.White
)
)
}
}
}
}
DetailScreen.kt
Composable
fun DetailScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalArrangement = Arrangement.Center
){
Text(
text = "Detail Screen",
fontSize = MaterialTheme.typography.h3.fontSize,
fontWeight = FontWeight.Bold
)
}
}
}
Notice the //TODO in LoginScreen and HomeScreen, we are going to need it later. And this is how they should look:
So far, so good. Now we have all that we need to start adding navigation to our screens.
First of all, add the navigation library to your build.gradle(app). Verify you add the last version, at this moment this is the last one:
implementation "androidx.navigation:navigation-compose:2.4.2"
Nice!, now go to the navigation package and add two new kotlin files: Screen.kt and NavGraph.kt
Open Screens.kt and add the next code:
sealed class Screens(val route: String) {
object Login: Screens("login_screen")
object Home: Screens("home_screen")
object Detail: Screens("Detail_screen")
}
As we can see this file contains a sealed class with three objects, each object corresponds to a screen and its routes. this is going to help us to have our routes organized.
Now, open the NavGraph.kt file and add the next code:
@Composable
fun NavGraph (navController: NavHostController){
NavHost(
navController = navController,
startDestination = Screens.Login.route)
{
composable(route = Screens.Login.route){
LoginScreen()
}
composable(route = Screens.Home.route){
HomeScreen()
}
composable(route = Screens.Detail.route){
DetailScreen()
}
}
}
In this file we can see in the NavGraph function, that needs navController parameter. Inside this function, we define the NavHost. In simple words, The NavHost is a container for navigation.
NavHost function has some parameters that we need to send:
navController: Which is the same that we are sending to ourNavGraphfunction.startDestination: This parameter we define which screen is going to be shown first.NavGraphBuilderthis builder is used to construct the graph, that's why you can see our routes with its screen defined here.
Now, let's go to our MainActivity.kt, here we need to call our NavGraph inside setContent / NavigationTheme / Surface
val navController = rememberNavController()
NavGraph(navController = navController)
This is how our MainActivity.kt should look:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
NavigationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
val navController = rememberNavController()
NavGraph(navController = navController)
}
}
}
}
}
Here, we need to create the navController that is going to be used in the app. So, first, we create a new variable navController by calling remeberNavController(). This remember function always returns the same object and allows us to not lose this object if we make configuration changes, like changing the screen orientation.
Now we can build the app and run the project.
Here we are seeing our Login Screen, which was defined as start destination in the NavGraph file.
So far, so good... Now we need to add the navigation to the buttons, to jump between screens. We are almost done!
Go to the NavGraph.kt file, here we need to add the parameter navController to the LoginScreen and HomeScreen, to allow them to use the navgraph when we click the button.
@Composable
fun NavGraph (navController: NavHostController){
NavHost(
navController = navController,
startDestination = Screens.Login.route)
{
composable(route = Screens.Login.route){
LoginScreen(navController)
}
composable(route = Screens.Home.route){
HomeScreen(navController)
}
composable(route = Screens.Detail.route){
DetailScreen()
}
}
}
Then open the LoginScreen.ktand HomeScreen.kt files and add the navController as a parameter for both of them.
@Composable
fun LoginScreen(navController: NavController)
@Composable
fun HomeScreen(navController: NavController)
Now inside LoginScreen.kt, search for the TODO comment inside the Button's onClick event:
//TODO: Navigate to Home Screen
Add the next code:
onClick = {
//TODO: Navigate to Home Screen
navController.navigate(Screens.Home.route)
}
)
Do the same for HomeScreen.kt, but change the route to DetailScreen.kt
onClick = {
//TODO: Navigate to Home Screen
navController.navigate(Screens.Detail.route)
}
So, one more time, build your app, run the project and see how is working now!
And that's it! we have our basic navigation :)
Here is the complete code in case you need it for reference
Compose Navigation Repo





Top comments (6)
Really nice and clear explanation, thanks!
What an excellent writing. I just started with android/kotlin/compose one week ago. This was the first tutorial that didn't require me to look up definitions and methods. I focused on understanding the implementation of building a navi without being distracted by looking up terminology.
Good job.
great
Too great. Too smart Elastic man
Elastic Man, nice game. Really top notch work.
Your tutorial helped me to put order in reading the fragmented and messy (in my opinion) official documentation on this topic.
Thank you very much