Implementación de Barra de Navegación Inferior en Android Compose
Clase 14 de 19 • Curso de Android: Modo Offline con Room y Realm
Resumen
La navegación en aplicaciones Android es un componente esencial para crear experiencias de usuario fluidas y coherentes. Implementar una barra de navegación inferior (Bottom Navigation Bar) permite a los usuarios acceder rápidamente a las principales secciones de la aplicación, mejorando significativamente la usabilidad. En este artículo, exploraremos cómo implementar esta funcionalidad utilizando Jetpack Compose, el moderno toolkit de UI para Android.
¿Cómo implementar una barra de navegación inferior en Jetpack Compose?
Para implementar una barra de navegación inferior en nuestra aplicación, necesitamos trabajar con Navigation en Compose. Este enfoque nos permite definir las diferentes pantallas de nuestra aplicación y navegar entre ellas de manera estructurada.
Primero, organizaremos nuestro código creando una estructura adecuada. Dentro del paquete "presentation", crearemos una nueva carpeta llamada "navigation" para mantener separados los componentes relacionados con la navegación.
Definición de las rutas de navegación
El primer paso es crear una clase sellada (sealed class) llamada "Screen" que contendrá la información necesaria para cada destino de navegación:
sealed class Screen(
val route: String,
val title: String,
val icon: ImageVector
) {
object Create : Screen(
route = "create",
title = "Crear",
icon = Icons.Default.Add
)
object Home : Screen(
route = "home",
title = "Órdenes",
icon = Icons.Default.Home
)
object PreOrders : Screen(
route = "list",
title = "Pre Órdenes",
icon = Icons.AutoMirrored.Filled.List
)
}
En este código, hemos definido tres destinos principales para nuestra aplicación:
- Create: Para crear nuevas preórdenes
- Home: La pantalla principal que muestra las órdenes
- PreOrders: Para listar todas las preórdenes creadas
Cada destino tiene una ruta única que se utilizará para la navegación, un título que se mostrará en la barra inferior y un icono que ayudará a los usuarios a identificar visualmente cada sección.
Implementación del componente de navegación inferior
Una vez definidas nuestras rutas, procedemos a crear el componente de la barra de navegación inferior:
@Composable
fun BottomNavigation(navController: NavController) {
val items = listOf(
Screen.Create,
Screen.Home,
Screen.PreOrders
)
NavigationBar {
val currentDestination = navController.currentBackStackEntryAsState().value?.destination?.route
items.forEach { screen ->
NavigationBarItem(
icon = { Icon(screen.icon, contentDescription = screen.title) },
label = { Text(screen.title) },
selected = currentDestination == screen.route,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
En este componente:
- Creamos una lista con los destinos de navegación
- Utilizamos
NavigationBar
como contenedor principal - Obtenemos la ruta actual para resaltar el ítem seleccionado
- Para cada destino, creamos un
NavigationBarItem
con su icono, etiqueta y comportamiento de navegación
El orden de los elementos en la lista determina su posición en la barra de navegación. En nuestro caso, "Create" estará a la izquierda, "Home" en el centro y "PreOrders" a la derecha.
Creación de la pantalla principal
Ahora necesitamos un componente principal que integre la barra de navegación con el contenido de cada pantalla:
@Composable
fun MainScreen(navController: NavController) {
Scaffold(
bottomBar = {
BottomNavigation(navController = navController)
}
) { padding ->
NavHost(
navController = navController,
startDestination = Screen.Home.route
) {
// Aquí se agregarán las composables para cada destino
// Por ahora, solo tenemos implementado el HomeScreen
composable(Screen.Home.route) {
HomeScreen(modifier = Modifier.padding(padding))
}
// Próximamente se agregarán las pantallas Create y PreOrders
}
}
}
En este componente:
- Utilizamos
Scaffold
para proporcionar la estructura básica de la pantalla - Configuramos la barra inferior con nuestro componente
BottomNavigation
- Utilizamos
NavHost
para gestionar la navegación entre destinos - Definimos
Screen.Home.route
como destino inicial - Aplicamos el padding del Scaffold a nuestros composables para evitar que el contenido quede oculto por la barra inferior
Integración en la actividad principal
Finalmente, integramos nuestro MainScreen
en la actividad principal:
@Composable
fun AppContent() {
val navController = rememberNavController()
MainScreen(navController = navController)
}
En lugar de mostrar directamente el HomeScreen
, ahora utilizamos nuestro MainScreen
que incluye la barra de navegación inferior y la lógica de navegación.
¿Cómo funciona la navegación en Jetpack Compose?
La navegación en Jetpack Compose se basa en el concepto de destinos y rutas. Cada pantalla de la aplicación se define como un destino con una ruta única. El NavController
es el componente central que gestiona la navegación entre estos destinos.
El flujo de navegación funciona de la siguiente manera:
- El usuario toca un elemento en la barra de navegación
- El
onClick
delNavigationBarItem
llama anavController.navigate()
con la ruta correspondiente - El
NavHost
detecta el cambio y muestra el composable asociado a esa ruta - La barra de navegación actualiza el elemento seleccionado basándose en la ruta actual
Las opciones como launchSingleTop = true
y restoreState = true
mejoran la experiencia de navegación evitando múltiples instancias de la misma pantalla y preservando el estado cuando el usuario regresa a una pantalla previamente visitada.
La implementación de una barra de navegación inferior en Jetpack Compose proporciona una forma intuitiva para que los usuarios naveguen por las principales secciones de nuestra aplicación. Este patrón de diseño, ampliamente utilizado en aplicaciones modernas, mejora significativamente la usabilidad y la experiencia general del usuario. ¿Has implementado barras de navegación en tus proyectos? Comparte tu experiencia en los comentarios.