Android Jetpack Compose Codelab
Android Jetpack Compose | Part 2 | Compose Destinations
Introduction
In Part 1 of the Jetpack Compose Codelab, we scaffolded the Landing, Signup, Login and Main screens for the Unicorn App.
In this codelab, we are going to use the Compose Destinations library in order to implement the navigation for the Unicorn App which is part of the Unicorn Stack.
Compose Destinations
Compose Destinations offers a cleaner API for navigation in Jetpack Compose and is therefore better suited for performing type-safe navigation using Jetpack Compose.
Get Started
In order to get started, we need to setup our build.gradle with the project dependencies
Add KSP Plugin
Note: The version you chose for the KSP plugin depends on the Kotlin version your project uses.
You can check https://github.com/google/ksp/releases for the list of KSP versions, then pick the last release that matches your Kotlin version. Example: If you’re using 1.8.20
Kotlin version, then the last KSP version is 1.8.20-1.0.10
.
plugins {
//...
id 'com.google.devtools.ksp' version '1.8.20-1.0.10' // Depends on your kotlin version
}
Add dependencies
Compose Destinations has multiple active versions. The higher one uses the latest versions for Compose and Accompanist, while the others use only stable versions.
In our case, we shall use version 1.9.54
// Compose Destinations
def compose_destinations_version = '1.9.54'
implementation "io.github.raamcosta.compose-destinations:core:$compose_destinations_version"
ksp "io.github.raamcosta.compose-destinations:ksp:$compose_destinations_version"
Usage Steps
Once the dependencies are added, we may continue on to perform the integration.
Step 1: Annotate your Screen Composables
Start by annotating your screen Composables with @Destination
:
In our case, we add @Destination to our HomeScreen, ContactScreen and NotificationScreen
@Destination
@Composable
fun HomeScreen(
navController: NavController
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(painterResource(
id = R.drawable.background_portrait_bg),
contentDescription = "",
contentScale = ContentScale.FillBounds,
modifier = Modifier.matchParentSize()
)
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
modifier = Modifier.clickable {
// TODO
},
text = "Welcome to Unicorn Home",
color = Color.White,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontWeight = FontWeight.Bold
)
}
}
}
@Preview
@Composable
fun HomeScreenPreview() {
HomeScreen(navController = rememberNavController())
}
Step 2: Define Navigation Arguments
Next, we need to add any navigation arguments.
Add any necessary navigation arguments to the function declaration. The library supports Parcelable
, Serializable
, Enum
types, and classes annotated with @kotlinx.serialization.Serializable
with no additional setup.
For now, we shall skip this step.
Step 3: Build the Project
Build the project using your IDE or by running ./gradlew kspDebugKotlin
in the terminal. This step generates all the Destinations, including a ProfileScreenDestination
file that will be used in the next step.
Step 4: Navigate to the Destination
Use the generated Destination invoke method to navigate to it. The method will have the correct typed arguments:
@RootNavGraph(start = true)
@Destination
@Composable
fun LandingScreen(
navController: NavController,
navigator: DestinationsNavigator
) {
LaunchedEffect(key1 = "LandingScreenAppeared") {
Log.d("UnicornApp", "navController: $navController, route: ${Screen.LoginScreen.route}")
}
val gradientColors = listOf(
PrimaryColor,
PrimaryColor
)
var showExpandedText by remember {
mutableStateOf(false)
}
Box(
modifier = Modifier
.fillMaxSize()
.background(
brush = createGradientEffect(
colors = gradientColors,
isVertical = true
)
),
contentAlignment = Alignment.Center,
) {
Column(
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 0.dp)
) {
Image(
painter = painterResource(id = R.drawable.unicorn_white),
contentDescription = stringResource(id = R.string.unicorn_content_description),
modifier = Modifier
.align(Alignment.CenterHorizontally)
.size(150.dp)
)
ClickableText(
text = AnnotatedString("UnicornApp"),
style = MaterialTheme.typography.h3.copy(color = Color.White),
modifier = Modifier
.align(Alignment.CenterHorizontally),
onClick = {
showExpandedText = !showExpandedText
}
)
Spacer(modifier = Modifier.height(8.dp))
AnimatedVisibility(visible = showExpandedText) {
Text(
text = "The Unicorn App Platform",
color = Color.White,
style = MaterialTheme.typography.body1.copy(color = Color.White),
textAlign = TextAlign.Center,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.fillMaxWidth()
)
}
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = {
// Use navigator.navigate
// instead of navController.navigate
/*
navController.navigate(
Screen.MainScreen.route
)
*/
navigator.navigate(
MainScreenDestination()
)
},
modifier = Modifier
.align(Alignment.CenterHorizontally)
.background(TransparentColor)
) {
Text(text = "GetStarted")
}
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = {
navController.navigate(
Screen.LoginScreen.route
)
},
modifier = Modifier
.align(Alignment.CenterHorizontally)
.background(TransparentColor)
) {
Text(text = "Login")
}
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = {
navController.navigate(
Screen.RegistrationScreen.route
)
},
modifier = Modifier
.align(Alignment.CenterHorizontally)
.background(TransparentColor)
) {
Text(text = "Sign Up")
}
Spacer(modifier = Modifier.height(8.dp))
}
}
}
@Composable
@Preview
fun LandingScreenPreview() {
LandingScreen(navigator = MockDestinationsNavigator())
}
Results
You may see the results of this below
The full source code for this codelab can be found at the branch named feature/develop_jetpack_compose_navigation_compose_destinations below
The next part of the CodeLabsPro | Jetpack Compose Series is available in Part 3