Jetpack Compose: Navigation multiple arguments

Introduction

Jetpack Compose has revolutionized the way developers build UI in Android by providing a declarative approach to UI design. With its integration of navigation components, handling multiple arguments across different screens becomes more streamlined and efficient. In this article, we explore how to pass multiple arguments between screens using Jetpack Compose’s navigation system in a simple yet practical example. The code walks through the process of setting up a navigation system that passes color names and their hexadecimal values from one screen to another, leveraging Jetpack Compose’s powerful toolkit.

This tutorial breaks down the key components of the Android Kotlin code, starting from setting up the scaffold and navigation controller to defining composable screens that handle and display the passed arguments. By the end, you'll have a solid understanding of how to manage navigation with multiple arguments in Jetpack Compose, making your apps more dynamic and user-interactive.

MainActivity and Scaffold Setup

The MainActivity class is where the app initializes and sets the content using setContent {}. In this content block, the GetScaffold() composable function is invoked. Scaffolds in Jetpack Compose are useful for creating a basic structure, which can include a top app bar, bottom navigation, and a content area.

The GetScaffold() function begins by creating a NavHostController using rememberNavController(). This controller is essential for managing navigation between composable screens. The scaffold also defines a TopAppBar that displays the title "Compose - Nav Multiple Arguments" and sets a background color. The main content of the scaffold is rendered by calling MainContent(), which in turn manages the navigation and the screen to be displayed.

Navigation Host and Screens

Inside the MainContent() composable, a Box layout is used to fill the screen and display the main navigation. The core of the navigation logic is encapsulated in the MainNavigation() composable. Here, a NavHost is defined, specifying the navController and the start destination, which is the "listScreen". The NavHost serves as a container for managing different routes or screens.

Two composable routes are defined within MainNavigation(). The first route, "listScreen", renders the ListScreen() composable, which displays a list of color names. The second route, "detailsScreen/{colorName}/{hexValue}", is designed to accept two arguments: colorName and hexValue. These values are passed through the navigation when transitioning from the list screen to the details screen, allowing for dynamic content display based on user interaction.

ListScreen: Navigating with Multiple Arguments

The ListScreen() composable contains a predefined map of color names and their corresponding hexadecimal values. This map is used to populate a list of clickable cards, each representing a different color. Using Jetpack Compose’s Column and Card components, the screen arranges these colors vertically with padding and spacing for a clean layout.

Each card is clickable, and upon clicking, the user is navigated to the detailsScreen with the associated colorName and hexValue. This is achieved by calling navController.navigate("detailsScreen/${it.key}/${it.value}"), where it.key refers to the color name and it.value refers to its hexadecimal value. By embedding these arguments into the navigation route, they are passed to the next screen seamlessly.

DetailsScreen: Displaying Passed Arguments

The DetailsScreen() composable is responsible for displaying the color name and hexadecimal value passed from the ListScreen. These values are accessed through the backStackEntry.arguments within the navigation route and are displayed using a Text composable. The values are placed within a Box layout that centers the content, providing a clean and simple display of the color information.

The text combines both the color name and hexadecimal value in a single string, formatted as "ColorName : HexValue". This composable demonstrates how to use multiple arguments passed from another screen and how to present them in a visually appealing and easy-to-understand format.

Summary

This example demonstrates how to implement navigation with multiple arguments in Jetpack Compose using Android Kotlin. Starting from the basic structure with Scaffold and NavController, the code efficiently manages transitions between screens while passing and displaying dynamic data. The ListScreen allows users to select a color, and the DetailsScreen displays the corresponding details by retrieving the passed arguments.

By following this pattern, developers can easily create multi-screen Android applications that handle complex navigation scenarios with ease. Jetpack Compose simplifies the navigation and argument-passing process, making it intuitive and more maintainable, ensuring a smoother developer experience when building dynamic UIs.


MainActivity.kt

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 - Nav Multiple Arguments"
                    )},
                    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}/{hexValue}",
            ){ backStackEntry ->
                DetailsScreen(
                    backStackEntry.arguments?.getString("colorName"),
                    backStackEntry.arguments?.getString("hexValue")
                )
            }
        }
    }


    @Composable
    fun ListScreen(navController: NavController){
        val maps = mapOf(
            Pair("Brick red","#CB4154"),
            Pair("Baby blue","#89CFF0"),
            Pair("Apple green","#8DB600"),
            Pair("Burnt sienna","#E97451"),
            Pair("Cameo pink","#EFBBCC")
        )
        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)
            )

            maps.forEach {
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(1.dp)
                        .height(50.dp)
                        .clickable {
                            navController
                                .navigate(
                                    "detailsScreen/${it.key}/${it.value}"
                                )
                        }
                ) {
                    Box(modifier = Modifier
                        .fillMaxSize()
                        .wrapContentSize(Alignment.Center)) {
                        Text(text = it.key)
                    }
                }
            }
        }
    }


    @Composable
    fun DetailsScreen(colorName:String?, hexValue:String?){
        Box(
            modifier = Modifier.fillMaxSize().padding(4.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "${colorName?.apply{}}" +
                        " : ${hexValue?.apply{}}",
                style = MaterialTheme.typography.h4,
                modifier = Modifier.padding(bottom = 24.dp),
                textAlign = TextAlign.Center
            )
        }
    }
}
More android jetpack compose tutorials