DEV Community

Cover image for Jetpack Compose: Navigation tutorial
Jess Barrientos
Jess Barrientos

Posted on

Jetpack Compose: Navigation tutorial

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:

android project

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.

files kotlin

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
                    )
                )
            }
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

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
                    )
                )
            }
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

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
            )
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Notice the //TODO in LoginScreen and HomeScreen, we are going to need it later. And this is how they should look:

screens example

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"


Enter fullscreen mode Exit fullscreen mode

Nice!, now go to the navigation package and add two new kotlin files: Screen.kt and NavGraph.kt

screens

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")
}



Enter fullscreen mode Exit fullscreen mode

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()
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

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 our NavGraph function.

  • startDestination: This parameter we define which screen is going to be shown first.

  • NavGraphBuilder this 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)


Enter fullscreen mode Exit fullscreen mode

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)
                }
            }
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

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.

login screenshot

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()
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Then open the LoginScreen.ktand HomeScreen.kt files and add the navController as a parameter for both of them.




@Composable
fun LoginScreen(navController: NavController)



Enter fullscreen mode Exit fullscreen mode



@Composable
fun HomeScreen(navController: NavController)


Enter fullscreen mode Exit fullscreen mode

Now inside LoginScreen.kt, search for the TODO comment inside the Button's onClick event:



 //TODO: Navigate to Home Screen


Enter fullscreen mode Exit fullscreen mode

Add the next code:




  onClick = {
            //TODO: Navigate to Home Screen
            navController.navigate(Screens.Home.route)
            }
)



Enter fullscreen mode Exit fullscreen mode

Do the same for HomeScreen.kt, but change the route to DetailScreen.kt




  onClick = {
            //TODO: Navigate to Home Screen
             navController.navigate(Screens.Detail.route)
            }



Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
erdo profile image
Eric Donovan

Really nice and clear explanation, thanks!

Collapse
 
fxmt2009 profile image
Ade

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.

Collapse
 
kururu95 profile image
kururu

great

Collapse
 
normanwolf profile image
normanwolf

Too great. Too smart Elastic man

Collapse
 
fxmt2009 profile image
Ade

Elastic Man, nice game. Really top notch work.

Collapse
 
gnicox profile image
gnicox

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