Conectar pantallas en una aplicación Android requiere un sistema de navegación robusto y moderno. Aquí se implementa la navegación entre una lista de tareas y un formulario de creación utilizando NavHost y NavController, las herramientas especializadas de Jetpack Compose para gestionar flujos de usuario de forma declarativa y eficiente.
¿Cómo configurar NavHost y NavController para conectar pantallas?
El primer paso es que el composable raíz de navegación reciba un NavHostController como parámetro [0:08]. Este controlador será el encargado de gestionar toda la pila de navegación. Dentro del composable, se define un NavHost que recibe dos elementos fundamentales: el NavController y un start destination, que indica cuál es la pantalla inicial.
En lugar de usar strings para identificar destinos, se adopta la forma más reciente de navegación en Android: clases serializables [0:33]. Para esto se crean dos clases:
HomeScreenDestination: representa la pantalla principal con la lista de tareas.
TaskScreenDestination: representa el formulario de creación.
Dentro del NavHost se declaran los composables asociados a cada destino. Cada bloque composable hace match con su destino correspondiente y renderiza el root composable adecuado [1:07].
¿Cómo se implementa la navegación entre pantallas?
Para que desde el home screen se pueda ir al task screen, se define una lambda de navegación que se conecta al botón de agregar tarea [1:23]. Esta lambda ejecuta navController.navigate(TaskScreenDestination), lo que empuja la nueva pantalla al stack de navegación.
Un detalle importante de arquitectura: no todas las acciones necesitan pasar por el ViewModel [1:58]. Cuando existe una relación uno a uno entre acción y evento, como el caso de presionar un botón y navegar, tiene más sentido interceptar esa acción directamente en el composable sin involucrar al ViewModel. Esto mantiene el código más limpio y directo.
¿Cómo regresar a la pantalla anterior con navigate up?
Desde la pantalla de creación de tareas, se necesita volver al home. Para esto se crea otra lambda llamada navigateBack que utiliza navController.navigateUp() [2:23]. Este método limpia el stack de navegación y devuelve al usuario a la pantalla anterior de forma segura.
El patrón es el mismo: se intercepta la acción correspondiente en el bloque onAction, y si la acción es de tipo back, se ejecuta la lambda. Para cualquier otra acción, se delega al ViewModel [2:38].
¿Dónde se crea e inyecta el NavController?
El NavController se crea en el MainActivity, un nivel por encima del NavigationRoute [2:55]. Se utiliza rememberNavController(), que es la forma estándar de crear y recordar la instancia del controlador a través de recomposiciones.
kotlin
val navController = rememberNavController()
NavigationRoute(navController = navController)
En el HomeScreen, el botón flotante del Scaffold conecta su onClick con la acción onAddTask, lo que dispara la navegación [3:14].
¿Cómo ordenar tareas por fecha tras la navegación?
Una vez que la navegación funciona correctamente, surge la necesidad de que las tareas recién creadas aparezcan primero. Para esto se agrega un campo date de tipo LocalDateTime con valor por defecto LocalDateTime.now() al modelo de tarea [4:12].
En el ViewModel del home, tanto las tareas pendientes como las completadas se ordenan usando sortByDescending sobre el campo date [4:27]. Esto garantiza que las tareas más recientes siempre aparezcan en las primeras posiciones de la lista.
kotlin
tasks.filter { !it.completed }.sortedByDescending { it.date }
tasks.filter { it.completed }.sortedByDescending { it.date }
También es necesario conectar el evento de devolverse automáticamente cuando una tarea se guarda exitosamente [3:50]. Dentro del TaskScreen, cuando se detecta el evento taskCreated, se invoca la lambda navigateBack para regresar al listado.
El resultado final es un flujo completo: dos pantallas conectadas donde el usuario puede listar tareas, crear nuevas y verlas ordenadas por fecha de creación. ¿Qué otros criterios de ordenamiento implementarías en tu lista de tareas?