Interacción y botones sin necesitar StatefulWidget: SnackBars, funciones auxiliares y Diálogos Modales
Un error conceptual muy habitual en quien empieza con Flutter es creer que para que un botón o elemento interactivo ejecute acciones (como navegar, mostrar avisos, desencadenar peticiones o abrir modales), la pantalla tiene que ser forzosamente un StatefulWidget.
En realidad, un StatelessWidget es plenamente capaz de gestionar eventos de usuario e interactividad enriquecida sin necesidad de mutabilidad interna.
Ejemplo práctico: Las tres técnicas fundamentales
Sección titulada «Ejemplo práctico: Las tres técnicas fundamentales»En el siguiente ejemplo funcional comprobamos cómo disparar SnackBars, delegar lógica a funciones auxiliares limpias y mostrar cuadros de diálogo modales (AlertDialog) desde un StatelessWidget:
import 'package:flutter/material.dart'; // Importa la librería base de componentes Material
class MiPantallaAcciones extends StatelessWidget { // Pantalla inmutable sin estado local const MiPantallaAcciones({super.key}); // Constructor constante
void _boton4Pulsado(BuildContext context) { // Función auxiliar fuera del árbol para código limpio debugPrint('Pulsado con lógica desacoplada'); // Registra evento en consola de depuración ScaffoldMessenger.of(context).showSnackBar( // Solicita mostrar notificación al mensajero const SnackBar(content: Text('¡Mensaje ejecutado desde función auxiliar!')), // Mensaje visual ); // Fin de showSnackBar } // Fin de _boton4Pulsado
@override // Sobreescribe el método build Widget build(BuildContext context) { // Retorna el árbol de la pantalla return Scaffold( // Estructura visual básica de la pantalla appBar: AppBar(title: const Text('Acciones en StatelessWidget')), // Barra superior con título body: Center( // Centra el contenido en pantalla child: Column( // Disposición vertical de widgets hijos mainAxisAlignment: MainAxisAlignment.center, // Centra verticalmente los elementos children: [ // Lista de widgets en la columna ElevatedButton( // Botón 1: lanza un SnackBar onPressed: () { // Callback al pulsar el botón ScaffoldMessenger.of(context).showSnackBar( // Muestra la notificación inferior const SnackBar( // Componente de notificación flotante content: Text('Iniciando sesión...'), // Texto informativo backgroundColor: Colors.teal, // Color de fondo personalizado duration: Duration(seconds: 2), // Tiempo de permanencia en pantalla ), // Fin de SnackBar ); // Fin de showSnackBar }, // Fin de onPressed child: const Text('Mostrar SnackBar'), // Texto del botón ), // Fin de ElevatedButton const SizedBox(height: 16), // Separación vertical de 16 píxeles ElevatedButton( // Botón 2: delega en función auxiliar onPressed: () => _boton4Pulsado(context), // Ejecuta función externa pasando context child: const Text('Función Auxiliar'), // Texto del botón ), // Fin de ElevatedButton const SizedBox(height: 16), // Separación vertical de 16 píxeles ElevatedButton( // Botón 3: abre cuadro de diálogo modal onPressed: () { // Callback al pulsar showDialog( // Muestra diálogo modal en la capa superior context: context, // Contexto para localizar el navegador builder: (context) => AlertDialog( // Construye el cuadro de diálogo title: const Text('Confirmación'), // Título del modal content: const Text('¿Estás seguro de que deseas continuar?'), // Pregunta actions: [ // Botones de decisión del modal TextButton( // Opción cancelar onPressed: () => Navigator.pop(context), // Cierra la ventana emergente child: const Text('Cancelar'), // Etiqueta del botón ), // Fin de TextButton FilledButton( // Opción confirmar con estilo destacado onPressed: () { // Callback de confirmación Navigator.pop(context); // Cierra la ventana modal }, // Fin de onPressed child: const Text('Aceptar'), // Etiqueta del botón de confirmación ), // Fin de FilledButton ], // Fin de lista de acciones ), // Fin de AlertDialog ); // Fin de showDialog }, // Fin de onPressed child: const Text('Abrir Diálogo de Confirmación'), // Texto del botón ), // Fin de ElevatedButton ], // Fin de lista children ), // Fin de Column ), // Fin de Center ); // Fin de Scaffold } // Fin del método build} // Fin de la clase MiPantallaAcciones