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 reutilizable1. 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 Materialimport '../pantalla_principal.dart'; // Importa la pantalla principal para navegaciónimport '../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 MenuLateral2. 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 Materialimport '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 MainApp3. 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.