Jetpack Compose App - Up Button

Objective:

Previously, we build the Detail Screen and handled the colors of the system navigation bar in the dark mode. The Detail Screen now looks and behaves very closely to the design. However, there is one major feature missing - the Up button. We have the back button in the navigation bar, but not the Up button on the screen itself.

To enable the up button on the Detail Screen, we first need to create the ScreenWithSecondaryAppBar @Composable

which will serve as as a container for any secondary screens needing an Up button. And then modify the navgraph to host all secondary screens within it.

Components built

Add or modify the following components:

  • ScreenWithSecondaryAppBar.kt: Scaffold-based composable with an Up Button and content for hosted composable
  • mainGraph.kt: Modify to wrap all secondary screens into ScreenWithSecondaryAppBar

Code

ScreenWithSecondaryAppBar

Add ScreenWithSecondaryAppBar.kt to the com.coroutines.thisdayinhistory.ui.appbar package in the app module:


package com.coroutines.thisdayinhistory.ui.appbar

import android.annotation.SuppressLint
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.navigation.NavController


@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ScreenWithSecondaryAppBar(
    navController: NavController,
    content: @omposable (modifier: Modifier)-> Unit) {
    Scaffold(
        topBar = {
            TopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = Color.Transparent,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = {
                    Text("")
                },
                navigationIcon = {
                    IconButton(onClick = {
                        navController.navigateUp()
                    }) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.ArrowBack,
                            contentDescription = "Back"
                        )
                    }
                },
            )
        },
    )
    { innerPadding ->
        content(Modifier.padding(innerPadding))
    }
}

Main Graph

Modify mainGraph.kt in the com.coroutines.thisdayinhistory.graph package in the app module:



package com.coroutines.thisdayinhistory.graph

import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import androidx.navigation.navigation
import com.coroutines.thisdayinhistory.LocalAppTheme
import com.coroutines.thisdayinhistory.components.rememberSystemUiController
import com.coroutines.thisdayinhistory.ui.appbar.ScreenWithSecondaryAppBar
import com.coroutines.thisdayinhistory.ui.configurations.ScreenConfiguration
import com.coroutines.thisdayinhistory.ui.configurations.StyleConfiguration
import com.coroutines.thisdayinhistory.ui.screens.about.AboutScreen
import com.coroutines.thisdayinhistory.ui.screens.detail.DetailScreen
import com.coroutines.thisdayinhistory.ui.screens.language.LanguageScreen
import com.coroutines.thisdayinhistory.ui.screens.main.HistoryScreen
import com.coroutines.thisdayinhistory.ui.screens.uitheme.ThemeScreen
import com.coroutines.thisdayinhistory.ui.viewmodels.ISettingsViewModel

fun NavGraphBuilder.mainGraph(
    navController: NavController,
    settingsViewModel : ISettingsViewModel
) {
    navigation(startDestination = MainNavOption.HistoryScreen.name, route = NavRoutes.MainRoute.name) {

        composable(MainNavOption.HistoryScreen.name) {
           HistoryScreen(navController = navController, settingsViewModel = settingsViewModel)
        }

        composable(
            MainNavOption.DetailScreen.name
        )
        { backStackEntry ->
            val systemUiController = rememberSystemUiController()
            val appBackgroundColor = MaterialTheme.colorScheme.background
            ScreenWithSecondaryAppBar(navController = navController) {
                DetailScreen(
                    modifier = Modifier,
                    navController = navController,
                    backHandler = {
                        systemUiController.setNavigationBarColor(appBackgroundColor)
                        navController.popBackStack()
                    },
                    darkThemeHandler = {
                        systemUiController.setNavigationBarColor(
                            color = Color.Transparent,
                            navigationBarContrastEnforced = false
                        )
                        systemUiController.setStatusBarColor(color = Color.Transparent)
                    },
                    styleConfiguration = StyleConfiguration(
                        ScreenConfiguration(LocalAppTheme.current),
                        MaterialTheme.typography,
                        "detail"
                    )
                )
            }
        }

        composable(
            MainNavOption.LanguagesScreen.name
        ) {
            ScreenWithSecondaryAppBar(navController = navController) {
                LanguageScreen(
                    navController = navController,
                    viewModel = settingsViewModel
                )
            }
        }

        composable(
            MainNavOption.ThemeScreen.name
        ) {
            ScreenWithSecondaryAppBar(navController = navController) {
                ThemeScreen(viewModel = settingsViewModel)
            }
        }

        composable(
            MainNavOption.AboutScreen.name
        ) {
            ScreenWithSecondaryAppBar(navController = navController) {
                AboutScreen(viewModel = settingsViewModel)
            }
        }
    }
}