Método 1: Usar Navigator.push
con MaterialPageRoute
Este método funciona de la siguiente manera:
Los diferentes widgets que componen las páginas de tu aplicación funcionan como una pila de hojas. Cuando usas Navigator.push
, Flutter apila una nueva página sobre esta pila, que actúa como un historial de navegación del usuario.
La transición entre páginas se gestiona con MaterialPageRoute
, que proporciona una animación de transición predeterminada basada en los principios de Material Design.
Además, como tu aplicación conserva en memoria la última página visitada, puedes regresar fácilmente con el método Navigator.pop
.
Comparado con otros métodos, la particularidad de Navigator.push
es que las páginas se construyen bajo demanda, solo cuando las utilizas. Flutter ignora la existencia de todo lo que no se usa durante el uso de tu aplicación.
Aquí tienes un ejemplo muy simple:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: PageUno(),
);
}
}
class PageUno extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página 1')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageDos()),
);
},
child: Text('Ir a la Página 2'),
),
),
);
}
}
class PageDos extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página 2')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context); // Regresar a la Página 1
},
child: Text('Regresar a la Página 1'),
),
),
);
}
}
Lo que sucede:
- Transición animada: Flutter realiza una animación de transición (por defecto, un deslizamiento hacia la izquierda).
- Memoria: La página anterior permanece en la pila de navegación.
- Gestión de estados: Si la página anterior utiliza un
StatefulWidget
, su estado se conserva hasta que se elimine.
Método 2: Navigator.pushReplacement
La función Navigator.pushReplacement
te permite reemplazar una página por otra sin que el usuario pueda regresar a la página anterior. Es útil para eventos como un inicio de sesión exitoso, donde no deseas que el usuario vuelva a la página anterior.
Cuando usas Navigator.pushReplacement
, la página actual se elimina de la pila de navegación y es reemplazada por la nueva página.
Aquí tienes un ejemplo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
}
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página de Inicio de Sesión')),
body: Center(
child: ElevatedButton(
onPressed: () {
// Reemplazar la página de inicio de sesión con la página principal
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
},
child: Text('Iniciar Sesión'),
),
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página Principal')),
body: Center(
child: ElevatedButton(
onPressed: () {
// Reemplazar la página principal con la página de inicio de sesión
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
);
},
child: Text('Cerrar Sesión'),
),
),
);
}
}
Método 3: Usar Navigator.pushNamed
Con Navigator.pushNamed
, defines nombres de rutas en MaterialApp
para cada página. Este enfoque centraliza la gestión de páginas y simplifica la navegación en aplicaciones con muchas páginas.
Como con Navigator.push
, también existe Navigator.pushReplacementNamed
, que permite al usuario ir a una nueva página sin la posibilidad de regresar a la página original.
Aquí tienes un ejemplo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/', // Página inicial
routes: {
'/': (context) => PageUno(),
'/pageDos': (context) => PageDos(),
'/pageTres': (context) => PageTres(),
},
);
}
}
class PageUno extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página 1')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/pageDos');
},
child: Text('Ir a la Página 2'),
),
),
);
}
}
class PageDos extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página 2')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/pageTres');
},
child: Text('Ir a la Página 3'),
),
),
);
}
}
class PageTres extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Página 3')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context); // Regresar a la Página 2
},
child: Text('Regresar a la Página 2'),
),
),
);
}
}
¿Qué sucede técnicamente?
- Las rutas se definen en el constructor de
MaterialApp
. Navigator.pushNamed
utiliza el nombre de una ruta ('/pageDos'
) para navegar.