Navegación basada en pila
Aprende cómo navegar de una página a otra en una aplicación Flutter.
Aprende a navegar entre pantallas con Navigator.push e implementa patrones de navegación adaptativos para diferentes tamaños de pantalla.
Qué lograrás
Pasos
1
Introducción
Introducción
Ahora que entiendes los slivers y el scroll, puedes implementar la navegación entre pantallas. En esta lección, actualizarás la vista de pantalla pequeña para que al tocar un grupo de contactos, se navegue a la lista de contactos de ese grupo.
Primero, revierte los cambios en el widget de layout adaptativo para que
muestre el ContactGroupsPage por defecto en pantallas pequeñas.
class _AdaptiveLayoutState extends State<AdaptiveLayout> {
int selectedListId = 0;
void _onContactListSelected(int listId) {
setState(() {
selectedListId = listId;
});
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final isLargeScreen = constraints.maxWidth > largeScreenMinWidth;
if (isLargeScreen) {
return _buildLargeScreenLayout();
} else {
return const ContactGroupsPage(); // Reverted
}
},
);
}
// ···
}
2
Añadir navegación a los grupos de contactos
Añadir navegación a los grupos de contactos
El ContactGroupsPage ya utiliza un _ContactGroupsView
y le proporciona un callback.
Ese callback debe ser actualizado para navegar cuando se toca un grupo,
en lugar de imprimir el grupo en la consola.
Asegúrate de que el callback onListSelected y las importaciones en
lib/screens/contact_groups.dart estén implementados de la siguiente manera:
import 'contacts.dart';
class ContactGroupsPage extends StatelessWidget {
const ContactGroupsPage({super.key});
@override
Widget build(BuildContext context) {
return _ContactGroupsView(
onListSelected: (list) => Navigator.of(context).push(
CupertinoPageRoute<void>(
title: list.title,
builder: (context) => ContactListsPage(listId: list.id),
),
),
);
}
}
Este pequeño bloque de código contiene la información nueva más importante en esta página.
Navigator.of(context) recupera el
widget Navigator más cercano del árbol de widgets.
El método push añade una nueva ruta a la pila del navegador y
muestra el widget devuelto por la propiedad builder.
Esta es la implementación más básica del uso de la navegación basada en pila,
donde se apilan (push) nuevas pantallas sobre la pantalla actual.
Para navegar de regreso a la pantalla anterior, usarías el método Navigator.pop.
CupertinoPageRoute crea transiciones de página al estilo iOS con
las siguientes características:
- Una animación de deslizamiento desde la derecha.
- Soporte para botón de retroceso automático.
- Manejo adecuado del título.
- Soporte para el gesto de deslizar para volver.
3
Crear el componente de barra lateral para pantallas grandes
Crear el componente de barra lateral para pantallas grandes
Para pantallas grandes, necesitas una barra lateral que no navegue, sino que
actualice el área de contenido principal.
Gracias a la refactorización del paso anterior,
la creación de este componente es más directa.
Añade este widget al final de lib/screens/contact_groups.dart:
/// A sidebar component for selecting contact groups on large screens.
class ContactGroupsSidebar extends StatelessWidget {
const ContactGroupsSidebar({
super.key,
required this.selectedListId,
required this.onListSelected,
});
final int selectedListId;
final void Function(int) onListSelected;
@override
Widget build(BuildContext context) {
return _ContactGroupsView(
selectedListId: selectedListId,
onListSelected: (list) => onListSelected(list.id),
);
}
}
Este componente de barra lateral reutiliza el _ContactGroupsView y
proporciona un callback diferente. En lugar de navegar,
llama a onListSelected con el ID de la lista tocada.
También pasa el selectedListId a _ContactGroupsView
para que
el elemento seleccionado pueda ser resaltado.
4
Crear la vista de detalle para pantallas grandes
Crear la vista de detalle para pantallas grandes
Para el diseño de pantalla grande, necesitas una vista de detalle que
no muestre controles de navegación. Al igual que la barra lateral,
esto se puede recrear reutilizando el _ContactListView.
Añade este widget al final de tu archivo contacts.dart:
class ContactListDetail extends StatelessWidget {
const ContactListDetail({super.key, required this.listId});
final int listId;
@override
Widget build(BuildContext context) {
return _ContactListView(listId: listId, automaticallyImplyLeading: false);
}
}
La vista de detalle reutiliza _ContactListView y establece
el parámetro automaticallyImplyLeading en false
para
ocultar el botón de retroceso, ya que la navegación es manejada por la barra lateral.
5
Conectar la barra lateral al diseño adaptativo
Conectar la barra lateral al diseño adaptativo
Ahora, conecta la barra lateral a tu diseño adaptativo.
Actualiza tu archivo adaptive_layout.dart para importar los archivos necesarios y
actualizar el diseño de pantalla grande:
import 'package:flutter/cupertino.dart';
import 'contact_groups.dart';
import 'contacts.dart';
Luego actualiza el método _buildLargeScreenLayout:
Widget _buildLargeScreenLayout() {
return CupertinoPageScaffold(
backgroundColor: CupertinoColors.extraLightBackgroundGray,
child: SafeArea(
child: Row(
children: [
SizedBox(
width: 320,
child: ContactGroupsSidebar(
selectedListId: selectedListId,
onListSelected: _onContactListSelected,
),
),
Container(width: 1, color: CupertinoColors.separator),
Expanded(child: ContactListDetail(listId: selectedListId)),
],
),
),
);
}
Este código crea el clásico diseño menú-detalle donde la barra lateral controla el contenido del área de detalle.
6
Probar el comportamiento de navegación adaptativo
Probar el comportamiento de navegación adaptativo
Haz Hot reload en tu aplicación y prueba la navegación:
Small screens (<600px width):
- Toca grupos de contactos para navegar a los detalles del contacto.
- Usa el botón de retroceso o un gesto de deslizar para volver.
- Este es un flujo clásico de navegación basada en pila.
Large screens (>600px width):
- Haz clic en los grupos de contactos en la barra lateral para actualizar la vista de detalle.
- No hay pila de navegación. La selección actualiza el área de contenido.
- Este es un patrón de interfaz maestro-detalle.
La aplicación elige automáticamente el patrón de navegación adecuado según el tamaño de la pantalla. Esto proporciona una experiencia óptima tanto en teléfonos como en tablets.
7
Revisión
Revisión
Qué lograste
Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.Navegué entre pantallas con Navigator.push
Navigator.of(context).push añade una nueva ruta a la pila de navegación. Esta es la base de la navegación basada en pila, donde las pantallas se apilan (push) una encima de otra y se desapilan (pop) para volver.
Usé CupertinoPageRoute para transiciones al estilo iOS
CupertinoPageRoute proporciona soporte para características de navegación nativas de iOS: animaciones de deslizamiento desde la derecha, botones de retroceso automáticos, manejo adecuado del título y soporte para el gesto de deslizar para volver.
Implementé patrones de navegación adaptativos
Configuraste diferentes patrones de navegación para pantallas pequeñas y grandes. Las pantallas pequeñas utilizan la navegación basada en pila donde al tocar un grupo se apila una nueva pantalla. Las pantallas grandes utilizan un patrón maestro-detalle donde al seleccionar un grupo se actualiza el panel de detalle sin navegación.
Completé la aplicación Rolodex
¡Has construido una aplicación de contactos completa al estilo iOS con layouts adaptativos, scroll avanzado, cabeceras colapsables con búsqueda y navegación responsiva. ¡Estos son patrones comunes utilizados en aplicaciones de producción!
8
Ponte a prueba
Ponte a prueba
Quiz de navegación
1 / 2Navigator.of(context).push do?Añade una nueva ruta a la pila de navegación, mostrándola encima de la pantalla actual.
¡Así es!
Push añade la nueva ruta a la pila, permitiendo a los usuarios volver a la pantalla anterior.
Elimina la pantalla actual de la pila de navegación.
No exactamente.
Eso es lo que hace
pop; push añade una nueva pantalla.Abre un cuadro de diálogo sobre la pantalla actual.
No exactamente.
Los diálogos usan
showDialog; Navigator.push navega a una pantalla completa.Reemplaza la pantalla actual con una nueva.
No exactamente.
Push añade a la pila;
pushReplacementreemplaza la pantalla actual.
Navigator.of(context).pop() do?Cierra la aplicación completa.
No exactamente.
Pop solo elimina la ruta superior; no cierra la aplicación.
Limpia todas las rutas y muestra la pantalla de inicio.
No exactamente.
Eso requeriría popUntil o pushAndRemoveUntil; pop solo elimina la ruta superior.
Elimina la ruta actual de la pila de navegación, volviendo a la pantalla anterior.
¡Así es!
Pop elimina la ruta superior de la pila, revelando la pantalla que está debajo.
Refresca la pantalla actual con nuevos datos.
No exactamente.
Pop navega hacia atrás; para refrescar, usarías setState u otra administración del State.
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.