Introduction
In modern Android app development, Jetpack Compose has emerged as a powerful and declarative UI framework, offering a fresh approach to building Android user interfaces. One of its most exciting features is seamless navigation between different screens within an app, including the ability to pass data, or arguments, between these screens. This capability is particularly useful for creating dynamic and interactive applications. In this article, we will explore a practical example of using Jetpack Compose to navigate between screens with arguments, written in Kotlin. The code demonstrates how to manage navigation from a list of color names to a detailed view of each color, highlighting the simplicity and flexibility of Jetpack Compose's navigation system.
This tutorial will break down the Kotlin code example step by step, explaining how navigation works in a Compose app, how to pass arguments between composables, and how to structure your app’s UI efficiently using Jetpack Compose’s NavHost
, composable
, and Scaffold
components. By the end, you will have a good understanding of how to implement similar navigation patterns in your own apps.
MainActivity: Entry Point of the App
The code begins in the MainActivity
class, which is the entry point of the application. Here, the onCreate
method calls setContent
, which is a Composable function that sets up the UI of the app using Jetpack Compose. This method replaces the traditional setContentView
used in XML-based layouts. The core UI is managed by the GetScaffold
composable, which defines the app's overall structure using the Scaffold
component.
GetScaffold: Structuring the UI
The GetScaffold
composable provides the layout structure for the app. It uses the Scaffold
component, a common layout pattern in Jetpack Compose that allows you to define key UI elements such as the TopAppBar
, content, and background color. In this case, the top bar displays a title ("Compose - Navigation Argument"), and the main content of the screen is determined by the MainContent
composable. Additionally, a navigation controller (NavHostController
) is created using rememberNavController
to manage the navigation between different screens.
MainNavigation: Setting Up Navigation Routes
The heart of the navigation logic is in the MainNavigation
composable. This function uses the NavHost
component to define the navigation graph, which consists of different routes or destinations. The startDestination
is set to "listScreen"
, indicating that the app should display the list of colors first. Two routes are defined in the NavHost
:
- ListScreen: Displays a list of color names.
- DetailsScreen: Displays the details of a selected color, accepting an argument (
colorName
) passed via the route.
ListScreen: Displaying Color Options
The ListScreen
composable displays a list of color names, which are defined in a simple list (list
). It uses a Column
layout to arrange the color options vertically. Each color name is wrapped in a Card
component to make it clickable, allowing users to select a color. When a user clicks on a color, the app navigates to the detailsScreen
route using the navController.navigate
method, passing the selected color as an argument (detailsScreen/$it
). This demonstrates how easy it is to define dynamic navigation routes in Jetpack Compose.
DetailsScreen: Showing Color Details
The DetailsScreen
composable is responsible for displaying the details of the selected color. It retrieves the colorName
argument from the navigation back stack using backStackEntry.arguments?.getString("colorName")
. The colorName
is then displayed in the center of the screen using a Text
composable, making this screen dynamic based on the color selected by the user. This composable is a great example of how to receive and display arguments passed through navigation.
Summary
This Kotlin example demonstrates how to use Jetpack Compose’s powerful navigation features to navigate between screens while passing arguments. By leveraging the NavHost
, composable
, and NavController
, developers can build highly interactive and dynamic Android apps with minimal boilerplate. The use of Jetpack Compose allows for a more intuitive and declarative way to manage UI elements, and passing arguments through navigation simplifies the process of creating dynamic content.
Jetpack Compose is changing the way Android apps are built, and this example illustrates just one of the many ways it can streamline app development. Whether you're building a small app with a few screens or a large, complex project, the flexibility and simplicity of Compose’s navigation system make it an excellent choice for modern Android development.
package com.cfsuman.jetpackcompose
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
GetScaffold()
}
}
@Composable
fun GetScaffold(){
val navController:NavHostController = rememberNavController()
Scaffold(
topBar = {
TopAppBar(
title = { Text(
text = "Compose - Navigation Argument"
)},
backgroundColor = Color(0xFFC0E8D5),
)
},
content = {MainContent(navController)},
backgroundColor = Color(0xFFEDEAE0),
)
}
@Composable
fun MainContent(navController: NavHostController){
Box(
modifier = Modifier.fillMaxSize(),
){
MainNavigation(navController)
}
}
@Composable
fun MainNavigation(navController: NavHostController){
NavHost(
navController = navController,
startDestination = "listScreen"
){
composable("listScreen"){ListScreen(navController)}
composable("detailsScreen/{colorName}"
){ backStackEntry ->
DetailsScreen(
backStackEntry.arguments?.getString("colorName")
)
}
}
}
@Composable
fun ListScreen(navController: NavController){
val list = listOf("Red","Green","Blue","Yellow","Black")
Column(
modifier = Modifier
.fillMaxWidth()
.padding(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalAlignment = Alignment.Start
) {
Text(
text = "List Screen",
style = MaterialTheme.typography.h4,
modifier = Modifier.padding(bottom = 24.dp)
)
list.forEach {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(1.dp)
.height(50.dp)
.clickable {
navController.navigate("detailsScreen/$it")
}
) {
Box(modifier = Modifier
.fillMaxSize()
.wrapContentSize(Alignment.Center)) {
Text(text = it)
}
}
}
}
}
@Composable
fun DetailsScreen(colorName:String?){
Box(
modifier = Modifier.fillMaxSize().padding(4.dp),
contentAlignment = Alignment.Center
) {
Text(
text = "Details Screen\n${colorName?.apply{}}",
style = MaterialTheme.typography.h4,
modifier = Modifier.padding(bottom = 24.dp),
textAlign = TextAlign.Center
)
}
}
}
- jetpack compose - Box gravity
- jetpack compose - Card padding
- jetpack compose - Card background color
- jetpack compose - How to use ModalDrawer
- jetpack compose - How to use BadgeBox
- jetpack compose - TopAppBar center title
- jetpack compose - TopAppBar menu
- jetpack compose - Snackbar action
- jetpack compose - Snackbar dismiss listener
- jetpack compose - How to use AndroidView
- jetpack compose - How to update AndroidView
- jetpack compose - How to use navigation controller
- jetpack compose - Navigation multiple arguments
- jetpack compose - Navigation arguments data type
- jetpack compose - Navigation object argument