Ir al contenido

Guía de Flutter para novatos - Miguel Páramos

FAQ sobre Flutter pal que no tiene ni idea de Flutter | 2º DAM · PMDM

Separación limpia de arquitectura: extracción de PantallaPrincipal y navegación con Menú Lateral (Drawer)

A medida que una aplicación crece, mantener todas las pantallas y widgets acumulados en un único archivo main.dart resulta inmanejable y vulnera el principio de responsabilidad única.

Para lograr una arquitectura limpia, profesional y escalable en Flutter, la estructura recomendada consiste en desacoplar cada pantalla y componente compartido en su propio archivo dentro de lib/:

# Estructura del proyecto en lib/ recomendada para arquitectura limpia:
lib/ # Directorio raíz de código fuente de la aplicación
├── main.dart # Punto de entrada: solo configura y arranca la App
├── pantalla_principal.dart # Pantalla de inicio de la aplicación
├── pantalla_colores.dart # Segunda pantalla interactiva con estado
└── widgets/ # Subdirectorio de componentes compartidos
└── menu_lateral.dart # Menú Drawer compartido y reutilizable

1. El Menú Lateral Reutilizable: lib/widgets/menu_lateral.dart

Sección titulada «1. El Menú Lateral Reutilizable: lib/widgets/menu_lateral.dart»
import 'package:flutter/material.dart'; // Importa componentes visuales de Material
import '../pantalla_principal.dart'; // Importa la pantalla principal para navegación
import '../pantalla_colores.dart'; // Importa la pantalla secundaria interactiva
class MenuLateral extends StatelessWidget { // Widget reutilizable del menú tipo Drawer
const MenuLateral({super.key}); // Constructor constante
@override // Sobreescribe el método build
Widget build(BuildContext context) { // Construye la estructura visual del menú
return Drawer( // Panel lateral desplegable nativo
child: ListView( // Lista scrolleable que contiene las opciones
padding: EdgeInsets.zero, // Elimina el padding por defecto para ocupar la cabecera
children: [ // Elementos verticales del menú
const DrawerHeader( // Cabecera destacada del menú lateral
decoration: BoxDecoration(color: Color(0xFF02569B)), // Fondo azul corporativo
child: Text( // Título de la cabecera
'Navegación de la App', // Texto superior
style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold), // Estilo blanco y negrita
), // Fin del widget Text
), // Fin del widget DrawerHeader
ListTile( // Opción 1: Pantalla Principal
leading: const Icon(Icons.home), // Icono de inicio
title: const Text('Pantalla Principal'), // Etiqueta de la opción
onTap: () { // Evento al pulsar
Navigator.pushReplacement( // Sustituye la ruta actual para no apilar pantallas infinitas
context, // Contexto de navegación
MaterialPageRoute(builder: (context) => const PantallaPrincipal()), // Ruta destino
); // Fin de pushReplacement
}, // Fin de onTap
), // Fin del widget ListTile
ListTile( // Opción 2: Pantalla de Colores
leading: const Icon(Icons.color_lens), // Icono de paleta de colores
title: const Text('Pantalla de Colores'), // Etiqueta de la opción
onTap: () { // Evento al pulsar
Navigator.pushReplacement( // Sustituye la ruta actual
context, // Contexto de navegación
MaterialPageRoute(builder: (context) => const PantallaColores()), // Ruta destino
); // Fin de pushReplacement
}, // Fin de onTap
), // Fin del widget ListTile
], // Fin de children
), // Fin de ListView
); // Fin de Drawer
} // Fin del método build
} // Fin de la clase MenuLateral

2. El Archivo Raíz: lib/main.dart (Minimalista)

Sección titulada «2. El Archivo Raíz: lib/main.dart (Minimalista)»
import 'package:flutter/material.dart'; // Importa la librería base de Material
import 'pantalla_principal.dart'; // Importa la vista inicial desacoplada
void main() { // Punto de arranque oficial de la aplicación
runApp(const MainApp()); // Infla el widget de configuración raíz
} // Fin de la función main
class MainApp extends StatelessWidget { // Clase raíz liviana: solo configura la app
const MainApp({super.key}); // Constructor constante
@override // Sobreescribe el método build
Widget build(BuildContext context) { // Retorna la configuración global
return const MaterialApp( // Contenedor global de Material Design
title: 'App Modular', // Título de la aplicación en el sistema
home: PantallaPrincipal(), // Enlaza directamente a la pantalla principal extraída
); // Fin de MaterialApp
} // Fin del método build
} // Fin de la clase MainApp

3. Cómo conectar el menú en cualquier pantalla

Sección titulada «3. Cómo conectar el menú en cualquier pantalla»

Basta con añadir la propiedad drawer: const MenuLateral() en el Scaffold de cada una de tus pantallas (tanto en PantallaPrincipal como en PantallaColores).

Flutter colocará de forma automática el botón de menú con el icono de hamburguesa (tres líneas horizontales) en el AppBar y habilitará el gesto táctil de arrastrar desde el borde izquierdo para abrirlo.