Route es una clase abstracta en Flutter que representa una pantalla o página individual en el historial de navegación de Navigator. Las implementaciones concretas de Route — MaterialPageRoute, CupertinoPageRoute y PlatformRoute — determinan cómo se muestra la pantalla y qué animación se utiliza durante la transición. A diferencia de un widget normal, Route tiene su propio ciclo de vida con los métodos didPush, didPop, didReplace y didChangeNext. Según la Flutter API Reference (2026), cada Route gestiona ModalBarrier, tiene en cuenta las características específicas de la plataforma (deslizar hacia atrás en iOS) y garantiza el aislamiento del estado entre pantallas.
Puntos clave
Route es la base del sistema de navegación de Flutter. Cada pantalla que el usuario ve en una aplicación está representada por un objeto Route ubicado en la pila de Navigator. Route abstrae la pantalla del código de control: Navigator añade y elimina Route, mientras que dentro de Route está la interfaz que ve el usuario. Esta arquitectura separa la responsabilidad entre la navegación y la visualización.
A diferencia del simple reemplazo de widgets, Route proporciona servicios no disponibles en los widgets normales: ModalBarrier (oscurecimiento del fondo cuando hay un diálogo abierto), control de animación de entrada y salida, manejo del botón de retroceso físico en Android e integración con la animación Hero para transiciones suaves entre pantallas.
Según Flutter Cookbook (2026), Route es un elemento clave para la animación Hero: un widget Hero en una Route anima automáticamente la transición a un widget Hero en la siguiente Route, creando un efecto de elemento “virtual”. Esto es posible precisamente porque Route mantiene ambas pantallas en la superposición durante la animación.
Route es la base tanto para aplicaciones móviles simples (a través de Navigator 1.0) como para escenarios complejos con enlaces profundos (Navigator 2.0). En Navigator 2.0, Route representa una Page que RouterDelegate convierte a partir de la configuración de la ruta. Por lo tanto, entender Route es esencial para trabajar con cualquier sistema de navegación de Flutter, independientemente del enfoque o paquete elegido.
Flutter proporciona varias implementaciones integradas de Route, cada una adaptando el comportamiento a una plataforma específica. Elegir el tipo correcto de Route afecta la experiencia del usuario: la animación Material en Android y la animación Cupertino en iOS crean la sensación de una aplicación “nativa”.
| Tipo de Route | Animación | Plataforma | Características |
|---|---|---|---|
| MaterialPageRoute | Deslizar de abajo arriba | Android, escritorio | Sombra en la transición, manejo automático de SafeArea |
| CupertinoPageRoute | Deslizar de derecha a izquierda | iOS, iPadOS | Gesto de deslizar hacia atrás, fondo transparente durante la transición |
| PlatformRoute | Selección automática | Todas las plataformas | Selecciona el tipo basado en TargetPlatform |
| PageRouteBuilder | Personalizada | Todas las plataformas | Control total sobre la animación mediante AnimationController |
MaterialPageRoute es la implementación de Route más utilizada. Anima la entrada de la nueva pantalla de abajo arriba con aparición gradual. Al salir, la pantalla se anima de arriba abajo, volviendo a su posición original. La barra de herramientas (AppBar) y el cuerpo de la pantalla se animan por separado, creando un efecto de jerarquía.
CupertinoPageRoute imita UINavigationController de iOS. La nueva pantalla entra desde la derecha, cubriendo la anterior. La característica clave es el soporte para el gesto interactivo de deslizar hacia atrás, implementado a través de CupertinoBackGestureDetector. Este gesto se maneja incluso durante la animación, proporcionando un comportamiento natural familiar para los usuarios de iPhone.
Route tiene su propio ciclo de vida, que difiere del ciclo de vida de un StatefulWidget normal. Comprender este ciclo es necesario para la inicialización adecuada de datos, suscripciones a streams y liberación de recursos al cerrar una pantalla.
El ciclo de vida de Route consta de cuatro etapas principales. Transición — Route se crea y se anima al entrar (se llama a didPush). Activo — Route se muestra completamente e interactúa con el usuario. Inactivo — otra Route cubre la actual (diálogo, hoja inferior), pero Route permanece en la pila. Destruido — Route se elimina de la pila y se destruye, se llaman a didPop y dispose.
Los métodos del ciclo de vida de Route pueden ser sobreescritos en una implementación personalizada. Por ejemplo, didPop se llama cuando Route se elimina de la pila — aquí se pueden guardar datos de borrador. didChangeNext se llama cuando la siguiente Route en la pila ha cambiado — útil para actualizar la interfaz cuando cambia el historial de navegación.
Según Flutter API Route.didPop (2026), es importante no confundir el ciclo de vida de Route con el ciclo de vida del State dentro de Route. StatefulWidget dentro de Route tiene su propio initState y dispose, que se llaman durante las etapas de Transición y Destruido respectivamente. Route vive más que su State interno — Route permanece en la superposición incluso cuando sus widgets están temporalmente ocultos por otra Route.
Route proporciona mecanismos para pasar datos tanto en la entrada (al crearse) como en la salida (al finalizar). El paso adecuado de datos a través de Route elimina la necesidad de variables globales e InheritedWidget, haciendo la navegación segura en cuanto a tipos y predecible.
Para pasar datos a una nueva pantalla, use el constructor del widget receptor o el parámetro arguments en Navigator.pushNamed. Dentro de Route, los datos son accesibles a través de RouteSettings.arguments, que se almacena en el objeto Route. Este enfoque funciona para todos los tipos de Route — MaterialPageRoute, CupertinoPageRoute e implementaciones personalizadas.
Para devolver datos, use el segundo argumento de Navigator.pop(context, result). Navigator.push devuelve Future
Al llamar a Navigator.push directamente con MaterialPageRoute, los datos se pasan a través del constructor de la pantalla de destino. No se utiliza MethodChannel — esta es una interacción pura de Dart. Este enfoque es preferible para el paso seguro de tipos de objetos complejos.
Veamos un ejemplo de creación de un Route personalizado con su propia animación y paso de datos. PageRouteBuilder permite definir animaciones de entrada y salida con control total sobre la curva de animación y la duración.
// Ruta personalizada con animación de deslizamiento
Navigator.push(context, PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return DetailPage(productId: '42');
},
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 0.3);
const end = Offset.zero;
final tween = Tween(begin: begin, end: end);
final offsetAnimation = animation.drive(tween);
return SlideTransition(position: offsetAnimation, child: child);
},
transitionDuration: const Duration(milliseconds: 400),
));
// Devolver datos desde la pantalla
ElevatedButton(
onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
child: const Text('Seleccionar'),
);
// Obtener resultado en la pantalla de llamada
final result = await Navigator.push(context, MaterialPageRoute(
builder: (context) => const SelectionPage(),
));
if (result != null) {
print('Seleccionado: ${result['selected']}');
}
En el ejemplo, PageRouteBuilder define una animación personalizada de deslizamiento desde abajo con transparencia. transitionDuration establece la velocidad de la animación. El código también demuestra el paso de resultados: la pantalla de detalle devuelve un Map con la selección del usuario, y la pantalla de llamada recibe estos datos a través del Future de push. Route garantiza un aislamiento completo: los borradores en la pantalla de detalle no afectan el estado de la lista.
Preguntas frecuentes
Route es un objeto que gestiona una pantalla a nivel de navegación: almacena animación, ModalBarrier y ciclo de vida. Widget es una descripción de una parte de la interfaz. Route contiene Widget dentro de sí mismo, pero también proporciona servicios (capa de superposición, animación Hero) no disponibles para los widgets normales. Una Route puede contener una jerarquía compleja de widgets de cualquier profundidad.
Use PageRouteBuilder con los parámetros pageBuilder (construcción de pantalla) y transitionsBuilder (definición de animación). En transitionsBuilder están disponibles animation (0.0–1.0) y secondaryAnimation para animaciones paralelas. Para control total, cree una subclase de Route y sobreescriba buildPage, createAnimationController y buildTransitions, dando acceso a AnimationController de bajo nivel.
Para pasar objetos complejos, use el constructor de la pantalla de destino al llamar a Navigator.push directamente o el parámetro arguments con pushNamed. Asegúrese de que el objeto sea serializable (Map, JSON o clase personalizada). Para el paso seguro de tipos en Flutter, use modelos freezed o json_serializable, que garantizan una deserialización correcta al pasar a través de RouteSettings.
Route.dispose no se llama si Route permanece en la pila de Navigator. Por ejemplo, al abrir una nueva Route, la Route anterior pasa al estado inactivo pero no se destruye — permanece en la pila para un retorno rápido. Dispose se llama solo cuando Route se elimina de la pila mediante pop, pushReplacement o pushAndRemoveUntil. Para liberar recursos, use dispose del State dentro de Route, no el dispose de la propia Route.
Use ModalRoute.of(context) para obtener la Route actual desde BuildContext. La propiedad ModalRoute.isActive muestra si la Route es la pantalla visible actualmente. ModalRoute.isCurrent — true si la Route es la parte superior de la pila. Para observar cambios en la pila, suscríbase a los observadores de Navigator a través de RouteAware y RouteObserver, que notifican sobre cambios de Route activa.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también