A navegación é fundamental en calquera aplicación móbil, xa que permite ao usuario moverse entre diferentes pantallas (ou “rutas” no contexto de Flutter). Flutter ofrece varias maneiras de xestionar a navegación, e aquí veremos as máis comúns e como pasar datos entre elas.
En Flutter, a navegación entre pantallas (ou pantallas secundarias, vistas, páxinas) xestiónase a través de rutas. Existen dúas formas principais de navegar:
- rutas anónimas
- rutas nomeadas.
Ademais, podes pasar datos á nova pantalla e recoller resultados cando se volve atrás.
➡️ push e pop (rutas anónimas) #
A forma máis básica de navegar en Flutter consiste en usar Navigator.push() xunto cun MaterialPageRoute para amosar unha nova pantalla, e Navigator.pop() para volver á anterior.
Cando se emprega push, a nova pantalla apílase sobre a actual, ocultándoa. Ao facer pop, a pantalla superior desaparece, revelando a anterior que quedara debaixo.
Este tipo de navegación utiliza rutas anónimas, xa que non se lle asigna un nome á pantalla de destino.
🧪 Exemplo: Navegar a unha nova pantalla #
ElevatedButton(
onPressed: () {
Navigator.push(
contexto,
MaterialPageRoute(builder: (contexto) => PantallaSecundaria()),
);
},
child: Text('Ir á Pantalla Secundaria'),
)
class PantallaSecundaria extends StatelessWidget {
@override
Widget build(BuildContext contexto) {
return Scaffold(
appBar: AppBar(title: Text('Pantalla Secundaria')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(contexto);
},
child: Text('Volver atrás'),
),
),
);
}
}
🧪 Outro exemplo #
🧾 Rutas nomeadas (pushNamed) #
Para aplicacións máis grandes, xestionar rutas anónimas pode volverse complicado. As rutas nomeadas ofrecen unha solución máis estruturada, asignando un nome único a cada ruta. Isto fai que o código sexa máis limpo e doado de manter, xa que non tes que construír o widget da ruta cada vez que navegas.
Para iso, definimos as rutas no MaterialApp.
✅ Definición no MaterialApp #
MaterialApp(
initialRoute: '/',
routes: {
'/': (contexto) => PantallaPrincipal(),
'/configuracion': (contexto) => PantallaConfiguracion(),
},
)
🧪 Navegar usando pushNamed #
Navigator.pushNamed(contexto, '/configuracion');
🧪 Outro exemplo #
📤 Pasar datos entre pantallas #
É moi común necesitar enviar datos dunha pantalla a outra. Hai varias formas de facelo:
- A través do construtor da ruta (para rutas anónimas). Esta é a forma máis directa e recomendada para pasar datos a unha nova pantalla cando usas
MaterialPageRoute. - A través de
arguments(para rutas nomeadas): Cando usas rutas nomeadas, podes pasar datos usando o argumentoargumentsdepushNamed. Despois, recuperas eses datos usandoModalRoute.of(context)!.settings.arguments.
🧪 Exemplo: A través do construtor da ruta #
Navigator.push(
contexto,
MaterialPageRoute(
builder: (contexto) => PantallaSaudo(nome: 'Diego'),
),
);
class PantallaSaudo extends StatelessWidget {
final String nome;
PantallaSaudo({required this.nome});
@override
Widget build(BuildContext contexto) {
return Scaffold(
appBar: AppBar(title: Text('Saúdo')),
body: Center(child: Text('Ola, $nome!')),
);
}
}
🧪 Outro exemplo: A través do construtor da ruta #
🧪 Exemplo: A través de arguments #
📥 Devolver resultados con pop #
Ademais de pasar datos cara adiante, tamén podes querer que unha pantalla devolva un resultado á pantalla que a chamou. Isto é útil, por exemplo, cando un usuario selecciona un elemento dunha lista e queres que esa selección se reflicta na pantalla anterior.
Podes facelo pasando un valor a Navigator.pop. A pantalla que chamou a outra pode esperar ese resultado usando await.
🧪 Exemplo: Escoller un valor e devolvelo #
// Pantalla principal
ElevatedButton(
onPressed: () async {
final resultado = await Navigator.push(
contexto,
MaterialPageRoute(builder: (contexto) => PantallaSeleccion()),
);
print('Resultado escollido: $resultado');
},
child: Text('Escoller opción'),
)
// Pantalla secundaria que devolve un valor
class PantallaSeleccion extends StatelessWidget {
@override
Widget build(BuildContext contexto) {
return Scaffold(
appBar: AppBar(title: Text('Selecciona unha opción')),
body: Column(
children: [
ListTile(
title: Text('Opción A'),
onTap: () {
Navigator.pop(contexto, 'A');
},
),
ListTile(
title: Text('Opción B'),
onTap: () {
Navigator.pop(contexto, 'B');
},
),
],
),
);
}
}