La navegación entre pantallas es el sistema que permite al usuario moverse de un lugar a otro dentro de tu app.
Piénsalo así: una app sin navegación es como una tienda Liverpool donde todas las secciones están encerradas con llave. El cliente entra, ve una sola vitrina y no puede ir a ningún otro lado. Frustrante, ¿verdad? La navegación abre esas puertas.
¿Por qué la navegación importa más de lo que crees?
¿Sabías que el 60% de los usuarios abandona una app en los primeros tres días? En muchos casos, la razón es simple: no entienden cómo moverse dentro de ella.
Rodrigo trabaja como desarrollador freelance en Monterrey. Construyó una app de catálogo para una ferretería local. El dueño del negocio se quejó: "Los clientes abren la app, ven los productos, pero no saben cómo llegar al carrito de compras." Rodrigo revisó su código y encontró el problema: había creado tres pantallas hermosas, pero nunca las había conectado entre sí. En Flutter, las pantallas no se conectan solas. Tú tienes que definir las rutas.
Ese mismo día, Rodrigo aprendió sobre el sistema de navegación de Flutter. En dos horas, la app ya funcionaba. El dueño de la ferretería quedó contento y Rodrigo cobró $4,500 extra por el ajuste.
El concepto de pila de navegación
Flutter maneja las pantallas como una pila de cartas. Cuando abres una pantalla nueva, la pones encima de la pila. Cuando regresas, la quitas de arriba y aparece la anterior.
Este sistema se llama Navigator en Flutter. Tiene dos acciones principales:
Navigator.push→ abre una pantalla nueva encimaNavigator.pop→ cierra la pantalla actual y regresa a la anterior
Es sencillo. No necesitas librerías externas para empezar. Flutter incluye esto desde el inicio.
Tu primera navegación: de pantalla A a pantalla B
Imagina que tienes una app con dos pantallas: PantallaInicio y PantallaDetalle. Quieres que al presionar un botón en la primera, el usuario llegue a la segunda.
Así se ve el código:
// Pantalla de inicio
class PantallaInicio extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Inicio')),
body: Center(
child: ElevatedButton(
child: Text('Ver detalle'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PantallaDetalle()),
);
},
),
),
);
}
}
// Pantalla de detalle
class PantallaDetalle extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Detalle')),
body: Center(
child: Text('Aquí va el detalle del producto'),
),
);
}
}
Observa algo importante: MaterialPageRoute es quien hace la transición animada. Flutter aplica automáticamente una animación suave al cambiar de pantalla. No tienes que programar esa animación tú mismo.
Cómo pasar información entre pantallas
Aquí es donde muchos desarrolladores principiantes se atascan. No basta con abrir una pantalla nueva. A veces necesitas enviarle datos.
Alejandra es diseñadora UX en Ciudad de México. Está construyendo su primera app real: un directorio de restaurantes de la colonia Roma. Cada restaurante tiene nombre, precio promedio y dirección. Cuando el usuario toca un restaurante, quiere ver su información completa.
Ella aprendió que puedes pasar datos a través del constructor de la pantalla destino:
// Pantalla de detalle recibe datos
class PantallaDetalle extends StatelessWidget {
final String nombre;
final String direccion;
final int precioPromedio;
PantallaDetalle({
required this.nombre,
required this.direccion,
required this.precioPromedio,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(nombre)),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Dirección: $direccion'),
Text('Precio promedio: \$$precioPromedio por persona'),
],
),
),
);
}
}
// Desde la pantalla de inicio, llamas así:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PantallaDetalle(
nombre: 'Tacos El Güero',
direccion: 'Álvaro Obregón 123, Roma Norte',
precioPromedio: 180,
),
),
);
Alejandra aplicó este patrón para todos sus restaurantes. La app quedó lista en un fin de semana. La publicó en Play Store y en dos semanas tenía más de 300 descargas en su colonia.
Rutas con nombre: organiza mejor tu app
Cuando tu app crece, manejar cada navegación con MaterialPageRoute directamente se vuelve desordenado. Es como guardar todos tus archivos en el escritorio sin carpetas.
Flutter tiene una solución: las rutas con nombre. Las defines todas en un solo lugar dentro de MaterialApp:
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => PantallaInicio(),
'/detalle': (context) => PantallaDetalle(),
'/carrito': (context) => PantallaCarrito(),
'/pago': (context) => PantallaPago(),
},
);
Luego navegas así desde cualquier parte de tu app:
Navigator.pushNamed(context, '/detalle');
Esto es exactamente como lo manejan apps grandes como las de FEMSA o Mercado Libre internamente: todas las rutas definidas en un mapa central. Tú sabes en todo momento qué pantallas existen y cómo se llaman.
El botón de regreso: Navigator.pop
Cuando el usuario quiere regresar a la pantalla anterior, usas Navigator.pop:
ElevatedButton(
child: Text('Regresar'),
onPressed: () {
Navigator.pop(context);
},
)
En Android, el botón físico de regreso ya hace esto automáticamente. En iOS, el gesto de deslizar desde la izquierda también. Pero siempre es buena práctica poner un botón visible de regreso. No asumas que todos los usuarios conocen esos gestos.
Errores comunes al navegar entre pantallas
Var ios desarrolladores cometen los mismos errores al principio. Aquí los más frecuentes para que tú los evites:
Error 1: Usar el context equivocado.
Si intentas navegar desde un lugar donde el context no tiene acceso al Navigator, la app falla. Solución: asegúrate de que tu MaterialApp esté por encima del widget donde llamas a Navigator.
Error 2: Olvidar el required en parámetros obligatorios.
Si declaras parámetros en el constructor de tu pantalla destino pero olvidas marcarlos como required, Flutter no te avisa del error hasta que la app se rompe en tiempo de ejecución. Márcalos siempre.
Error 3: Apilar pantallas sin control.
Si usas Navigator.push muchas veces seguidas sin hacer pop, acumulas pantallas en memoria. El usuario presiona regresar y tiene que pasar por diez pantallas antes de salir. Usa Navigator.pushReplacement cuando no necesites regresar a la pantalla anterior.
Error 4: No manejar el regreso con datos.
¿Sabías que Navigator.pop puede devolver un valor? Por ejemplo, si el usuario selecciona un producto en una pantalla de búsqueda, puedes regresar ese producto a la pantalla anterior. Se hace así:
// En la pantalla destino, regresas un valor:
Navigator.pop(context, 'producto_seleccionado');
// En la pantalla origen, recibes el valor:
final resultado = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => PantallaBusqueda()),
);
print('El usuario eligió: $resultado');
Este patrón es muy útil en apps de e-commerce, como un catálogo estilo Bimbo donde el usuario elige sabores o presentaciones.
La diferencia entre push y pushReplacement
Esta distinción salva muchos dolores de cabeza.
Navigator.push→ agrega una pantalla encima. El usuario puede regresar.Navigator.pushReplacement→ reemplaza la pantalla actual. El usuario no puede regresar a ella.
¿Cuándo usar pushReplacement? En la pantalla de inicio de sesión. Una vez que el usuario entra a su cuenta, no quieres que al presionar regresar vuelva al login. Reemplazas esa pantalla con el home de la app.
Carlos construye una app de control de gastos para pequeñas empresas en Puebla. Sus clientes son tiendas que facturan entre $80,000 y $200,000 al mes. Cuando implementó el login con push normal, los usuarios regresaban accidentalmente a la pantalla de acceso. Con pushReplacement, ese problema desapareció. Pequeño cambio, gran diferencia en la experiencia.
Lo que aprendiste hoy
La navegación es el esqueleto invisible de cualquier app. Sin ella, tienes pantallas bonitas pero aisladas. Con ella, tienes una experiencia fluida que el usuario entiende y disfruta.
Practica creando una app de tres pantallas: inicio, detalle y confirmación. Pasa datos entre ellas. Verás que en menos de una hora ya tienes algo que funciona como una app real.