Jetpack Compose Bottom Navigation

Jetpack Compose bottom navigation is a Material Design component that provides tab-based navigation at the bottom of your screen. Unlike traditional Android development where you'd use XML layouts and ViewPager, Jetpack Compose bottom navigation uses declarative programming principles to create responsive and interactive navigation experiences.

The core component for Jetpack Compose bottom navigation is BottomNavigation, which works alongside BottomNavigationItem composables to create individual navigation tabs. When implementing Jetpack Compose bottom navigation, you'll typically combine these components with Jetpack Navigation Compose library for full navigation functionality.

Essential Components for Jetpack Compose Bottom Navigation

BottomNavigation Composable

The BottomNavigation composable serves as the container for your Jetpack Compose bottom navigation implementation. This component provides the foundation for organizing navigation items and handling user interactions.

BottomNavigation(  
    backgroundColor = MaterialTheme.colors.primary,  
    contentColor = Color.White  
) {  
    // Navigation items go here  
}  

The backgroundColor property controls the background color of your Jetpack Compose bottom navigation bar, while contentColor determines the default color for content within the navigation bar.

BottomNavigationItem Properties

Each BottomNavigationItem in your Jetpack Compose bottom navigation setup supports several key properties:

selected: A Boolean value indicating whether the current item is selected. This property is essential for Jetpack Compose bottom navigation state management.

BottomNavigationItem(  
    selected = currentRoute == "home",  
    onClick = { navController.navigate("home") }  
)  

onClick: A lambda function that executes when users tap the navigation item. In Jetpack Compose bottom navigation, this typically involves navigation actions.

icon: The composable that displays the navigation item's icon. Most Jetpack Compose bottom navigation implementations use Material Icons.

icon = {  
    Icon(  
        imageVector = Icons.Default.Home,  
        contentDescription = "Home"  
    )  
}  

label: An optional text label that appears below the icon in your Jetpack Compose bottom navigation.

label = {  
    Text("Home")  
}  

enabled: Controls whether the navigation item responds to user interactions in your Jetpack Compose bottom navigation.

alwaysShowLabel: Determines whether labels remain visible even when items aren't selected in Jetpack Compose bottom navigation.

selectedContentColor and unselectedContentColor: These properties control the visual appearance of selected and unselected items in Jetpack Compose bottom navigation.

Setting Up Navigation Controller

Jetpack Compose bottom navigation works seamlessly with NavController for handling navigation logic. The NavController manages the navigation stack and coordinates with your Jetpack Compose bottom navigation implementation.

val navController = rememberNavController()  

You'll use navController.navigate() within your Jetpack Compose bottom navigation onClick handlers to navigate between destinations. The currentBackStackEntryAsState() function helps track the current destination for Jetpack Compose bottom navigation state management.

val navBackStackEntry by navController.currentBackStackEntryAsState()  
val currentRoute = navBackStackEntry?.destination?.route  

Creating Navigation Items Data Class

For organized Jetpack Compose bottom navigation implementations, create a data class representing navigation items:

data class NavigationItem(  
    val title: String,  
    val icon: ImageVector,  
    val route: String  
)  

This approach makes your Jetpack Compose bottom navigation code more maintainable and allows easy modification of navigation items.

Handling Navigation State

Jetpack Compose bottom navigation requires proper state management to highlight the currently selected item. You'll observe the NavController's back stack to determine which navigation item should appear selected.

The currentBackStackEntryAsState() function provides a Compose State that updates whenever navigation occurs in your Jetpack Compose bottom navigation setup. This ensures your navigation bar reflects the current screen accurately.

Customizing Appearance

Jetpack Compose bottom navigation offers extensive customization options. You can modify colors, typography, and spacing to match your app's design requirements.

Material Theme integration allows your Jetpack Compose bottom navigation to automatically adapt to your app's color scheme. However, you can override default colors using the backgroundColor, contentColor, selectedContentColor, and unselectedContentColor properties.

Integration with NavHost

Your Jetpack Compose bottom navigation setup requires integration with NavHost to define navigation destinations:

NavHost(  
    navController = navController,  
    startDestination = "home"  
) {  
    composable("home") { HomeScreen() }  
    composable("profile") { ProfileScreen() }  
    composable("settings") { SettingsScreen() }  
}  

This integration ensures that Jetpack Compose bottom navigation actions trigger appropriate screen transitions.

Complete Jetpack Compose Bottom Navigation Example

Here's a comprehensive example demonstrating Jetpack Compose bottom navigation implementation with all necessary components:

import androidx.compose.foundation.layout.*  
import androidx.compose.material.*  
import androidx.compose.material.icons.Icons  
import androidx.compose.material.icons.filled.*  
import androidx.compose.runtime.*  
import androidx.compose.ui.Alignment  
import androidx.compose.ui.Modifier  
import androidx.compose.ui.graphics.Color  
import androidx.compose.ui.graphics.vector.ImageVector  
import androidx.compose.ui.text.font.FontWeight  
import androidx.compose.ui.text.style.TextAlign  
import androidx.compose.ui.unit.dp  
import androidx.compose.ui.unit.sp  
import androidx.navigation.NavController  
import androidx.navigation.NavHostController  
import androidx.navigation.compose.NavHost  
import androidx.navigation.compose.composable  
import androidx.navigation.compose.currentBackStackEntryAsState  
import androidx.navigation.compose.rememberNavController  
  
// Data class for navigation items  
data class NavigationItem(  
    val title: String,  
    val icon: ImageVector,  
    val route: String  
)  
  
// Main composable with Jetpack Compose bottom navigation  
@Composable  
fun MainScreenWithBottomNavigation() {  
    val navController = rememberNavController()  
      
    // Define navigation items for Jetpack Compose bottom navigation  
    val navigationItems = listOf(  
        NavigationItem("Home", Icons.Default.Home, "home"),  
        NavigationItem("Search", Icons.Default.Search, "search"),  
        NavigationItem("Favorites", Icons.Default.Favorite, "favorites"),  
        NavigationItem("Profile", Icons.Default.Person, "profile")  
    )  
      
    Scaffold(  
        bottomBar = {  
            JetpackComposeBottomNavigation(  
                navController = navController,  
                navigationItems = navigationItems  
            )  
        }  
    ) { paddingValues ->  
        NavHost(  
            navController = navController,  
            startDestination = "home",  
            modifier = Modifier.padding(paddingValues)  
        ) {  
            composable("home") {  
                ScreenContent(  
                    title = "Home Screen",  
                    description = "Welcome to Jetpack Compose bottom navigation demo!"  
                )  
            }  
            composable("search") {  
                ScreenContent(  
                    title = "Search Screen",  
                    description = "Search functionality with Jetpack Compose bottom navigation"  
                )  
            }  
            composable("favorites") {  
                ScreenContent(  
                    title = "Favorites Screen",  
                    description = "Your favorite items using Jetpack Compose bottom navigation"  
                )  
            }  
            composable("profile") {  
                ScreenContent(  
                    title = "Profile Screen",  
                    description = "User profile with Jetpack Compose bottom navigation"  
                )  
            }  
        }  
    }  
}  
  
// Jetpack Compose bottom navigation implementation  
@Composable  
fun JetpackComposeBottomNavigation(  
    navController: NavController,  
    navigationItems: List<NavigationItem>  
) {  
    val navBackStackEntry by navController.currentBackStackEntryAsState()  
    val currentRoute = navBackStackEntry?.destination?.route  
      
    BottomNavigation(  
        backgroundColor = MaterialTheme.colors.primary,  
        contentColor = Color.White,  
        elevation = 8.dp  
    ) {  
        navigationItems.forEach { item ->  
            BottomNavigationItem(  
                selected = currentRoute == item.route,  
                onClick = {  
                    navController.navigate(item.route) {  
                        // Pop up to start destination to avoid building up back stack  
                        popUpTo(navController.graph.startDestinationId) {  
                            saveState = true  
                        }  
                        // Avoid multiple copies of same destination  
                        launchSingleTop = true  
                        // Restore state when reselecting previously selected item  
                        restoreState = true  
                    }  
                },  
                icon = {  
                    Icon(  
                        imageVector = item.icon,  
                        contentDescription = item.title,  
                        modifier = Modifier.size(24.dp)  
                    )  
                },  
                label = {  
                    Text(  
                        text = item.title,  
                        fontSize = 12.sp,  
                        maxLines = 1  
                    )  
                },  
                selectedContentColor = Color.White,  
                unselectedContentColor = Color.White.copy(alpha = 0.6f),  
                alwaysShowLabel = true  
            )  
        }  
    }  
}  
  
// Screen content composable for demonstration  
@Composable  
fun ScreenContent(  
    title: String,  
    description: String  
) {  
    Column(  
        modifier = Modifier  
            .fillMaxSize()  
            .padding(16.dp),  
        horizontalAlignment = Alignment.CenterHorizontally,  
        verticalArrangement = Arrangement.Center  
    ) {  
        Text(  
            text = title,  
            fontSize = 24.sp,  
            fontWeight = FontWeight.Bold,  
            textAlign = TextAlign.Center  
        )  
          
        Spacer(modifier = Modifier.height(16.dp))  
          
        Text(  
            text = description,  
            fontSize = 16.sp,  
            textAlign = TextAlign.Center,  
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.7f)  
        )  
    }  
}  
  
// Usage in your Activity or main composable  
@Composable  
fun MyApp() {  
    MaterialTheme {  
        MainScreenWithBottomNavigation()  
    }  
}  

To use this Jetpack Compose bottom navigation example in your Android project, add these dependencies to your build.gradle.kts (Module: app):

dependencies {  
    implementation "androidx.compose.ui:ui:1.5.4"  
    implementation "androidx.compose.ui:ui-tooling-preview:1.5.4"  
    implementation "androidx.compose.material:material:1.5.4"  
    implementation "androidx.activity:activity-compose:1.8.1"  
    implementation "androidx.navigation:navigation-compose:2.7.5"  
    implementation "androidx.compose.material:material-icons-extended:1.5.4"  
}  

This complete Jetpack Compose bottom navigation implementation demonstrates how to create a fully functional navigation system with proper state management, smooth transitions, and Material Design compliance. The example shows how Jetpack Compose bottom navigation integrates with modern Android architecture patterns while providing an intuitive user experience.

Your Jetpack Compose bottom navigation setup will now handle navigation between different screens while maintaining proper visual feedback for the currently selected tab. The implementation follows Android development best practices and ensures your Jetpack Compose bottom navigation remains responsive and accessible across different device configurations.