Easy app to indicate completely different screens in Jetpack Compose and navigate between them.
This text was initially printed at vtsen.hashnode.dev on April 23, 2022.
I created this easy app to check out the navigation component in Jetpack Compose. That is how the app appears like.
These are the steps to implement this easy app.
1. Add Navigation Compose Library
In appbuild.gradle
, add this dependency.
dependencies {
implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
}
2. Create NavHostController
NavHostController
is required to construct the navigation graph within the subsequent step which is used to navigate to completely different screens.
Create this NavHostController
utilizing rememberNavController()
in your root composable operate and move that into the BuildNavGraph()
composable operate.
@Composable
personal enjoyable MainScreen() {
SimpleNavComposeAppTheme {
val navController = rememberNavController()
BuildNavGraph(navController)
}
}
3. Construct Navigation Graph
The navigation graph appears like this:
- Login Display -> Dwelling Display -> Profile Display
- Login Display -> Dwelling Display -> Search Display
Login display screen is the beginning vacation spot. Dwelling display screen takes no navigation argument. Profile display screen takes 2 navigation arguments and search display screen takes 1 navigation argument.
To construct the navigation graph, you employ NavHost()
composable operate and NavGraphBuilder.composable()
operate to construct every composable display screen.
enjoyable BuildNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = "login"
) {
composable(route = "login") {
//name LoginScreen composable operate right here
}
composable(route = "residence") {
//name HomeScreen composable operate right here
}
...
}
}
To navigate to residence display screen:
navController.navigate("residence")
To pop again present stack:
navController.popBackStack()
To pop as much as login display screen:
navController.popBackStack(NavRoute.Login.path, inclusive = false)
Navigation With Arguments
navGraphBuilder.composable
has 2 parameters – route
and arguments
. To navigation with argument, we need to replace each route
and arguments
parameters.
That is route format for profile display screen. id
is the primary parameter. showDetails
is the second parameter.
route = "profile/{id}/{showDetails}"
The arguments
parameter appears like this:
arguments = listOf(
navArgument("id") {
sort = NavType.IntType
}
,
navArgument("showDetails") {
sort = NavType.BoolType
}
)
You’ll be able to specify the NavType
of the parameter. You can too set the defaultValue
to make the argument elective.
...
navArgument("showDetails") {
sort = NavType.BoolType
defaultValue = false
}
...
I personally will keep away from utilizing
defautValue
as a result of it requires your path to comply with sure format (i.e."profile/{id}/?showDetails={showDetails}"
).?showDetails
is the elective arguement to permit you specify thedefaultValue
.
To retrieve the argument worth, you employ the NavBackStackEntry.arguments
:
composable(
...
) { navBackStackEntry ->
val args = navBackStackEntry.arguments
// get id param worth
val id = args?.getInt("id")!!
// get showDetails param worth
val showDetails = args?.getBoolean("showDetails")!!
// name profile display screen composable operate right here
...
}
That is an instance to navigate to profile display screen.
val id = 7
val showDetails = true
navController.navigate("profile/$id/$showDetails")
Any Route Format Is Effective!
As a substitute of utilizing this (which I desire as a result of it’s the easiest type):
route = "profile/{id}/{showDetails}"
You should utilize this (required if you would like showDetails
to be elective):
route = "profile/{id}/?showDetails={showDetails}"
Or this (required if you would like each id
and showDetails
to be elective): :
route = "profile/?id={id}/?showDetails={showDetails}"
However please do NOT use this:
route = "profile/{id}{showDetails}"
Please be sure to at the least put a separator (any string) between the navigation parameters. This navigation parameters might be parsed wrongly particularly they’re similar knowledge sort.
When you change the route format, it is advisable replace the navigation name too. For instance:
val id = 7
val showDetails = true
navController.navigate("profile/$id/?showDetails=$showDetails")
Too A lot Boilerplate Code
You will have seen, the hard-coded strings are in every single place. One mistake can simply crash the app. It’s susceptible to errors.
So what I did is to create this NavRoute
class that has all of the hard-coded strings there. I additionally embody a utility capabilities (i.e. withArgs()
to construct the navigation path and withArgsFormat()
to construct the route
format string.
sealed class NavRoute(val path: String) {
object Login: NavRoute("login")
object Dwelling: NavRoute("residence")
object Profile: NavRoute("profile") {
val id = "id"
val showDetails = "showDetails"
}
object Search: NavRoute("search") {
val question = "question"
}
// construct navigation path (for display screen navigation)
enjoyable withArgs(vararg args: String): String {
return buildString {
append(path)
args.forEach{ arg ->
append("/$arg")
}
}
}
// construct and setup route format (in navigation graph)
enjoyable withArgsFormat(vararg args: String) : String {
return buildString {
append(path)
args.forEach{ arg ->
append("/{$arg}")
}
}
}
}
Some utilization examples:
// navigate to residence
navController.navigate(NavRoute.Dwelling.path)
// navigate to look
navController.navigate(NavRoute.Search.withArgs(question))
// setup route for search display screen with question param
route = NavRoute.Search.withArgsFormat(NavRoute.Search.question)
Closing Ideas
I am unsure my NavRoute approach above is the great one. I am additionally unsure if it makes the code unreadable? Possibly a bit? Nevertheless, it at the least can do away with many hard-coded strings and no extra boilerplate code.
There’s a Compose Locations library which removes much more boilerplate code. I feel it’s higher to grasp the basic first earlier than making an attempt out this library.
Listed below are the steps to transform this app to make use of this library:
Supply Code
GitHub Repository: Demo_SimpleNavigationCompose