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 ourNavGraph
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)
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.kt
and 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