Ejemplo práctico de StatefulWidget: Pantalla interactiva que cambia de color y texto al pulsar un botón
Para comprender en detalle cómo opera la reactividad en Flutter con StatefulWidget, el siguiente ejemplo funcional implementa una pantalla interactiva que rota cíclicamente entre cuatro combinaciones de color de fondo y textos descriptivos cada vez que el usuario presiona un botón:
Código: pantalla_colores.dart
Sección titulada «Código: pantalla_colores.dart»import 'package:flutter/material.dart'; // Importa el catálogo de diseño Material
class PantallaColores extends StatefulWidget { // Widget con estado interactivo propio const PantallaColores({super.key}); // Constructor constante de la pantalla
@override // Sobreescribe la creación de estado State<PantallaColores> createState() => _PantallaColoresState(); // Instancia el objeto de estado} // Fin de la clase PantallaColores
class _PantallaColoresState extends State<PantallaColores> { // Objeto de estado mutable persistente int _colorIndex = 0; // Índice numérico del color actualmente visible
final List<Map<String, dynamic>> _colores = [ // Colección de opciones temáticas { // Opción 0: Azul 'nombre': 'Azul Suave', // Nombre descriptivo 'color': const Color(0xFFBFDBFE), // Tono de fondo 'textoColor': const Color(0xFF1E3A8A), // Tono del texto para alto contraste }, // Fin de opción 0 { // Opción 1: Verde 'nombre': 'Verde Menta', // Nombre descriptivo 'color': const Color(0xFFBBF7D0), // Tono de fondo 'textoColor': const Color(0xFF065F46), // Tono del texto }, // Fin de opción 1 { // Opción 2: Ámbar 'nombre': 'Ámbar Cálido', // Nombre descriptivo 'color': const Color(0xFFFED7AA), // Tono de fondo 'textoColor': const Color(0xFF9A3412), // Tono del texto }, // Fin de opción 2 { // Opción 3: Lavanda 'nombre': 'Lavanda', // Nombre descriptivo 'color': const Color(0xFFE9D5FF), // Tono de fondo 'textoColor': const Color(0xFF581C87), // Tono del texto }, // Fin de opción 3 ]; // Fin de la lista de colores
void _rotarColor() { // Método de negocio que actualiza el estado setState(() { // Notifica al framework que debe redibujar la vista _colorIndex = (_colorIndex + 1) % _colores.length; // Avanza cíclicamente de 0 a 3 }); // Fin de setState } // Fin de _rotarColor
@override // Sobreescribe el método build Widget build(BuildContext context) { // Reconstruye la interfaz con los datos vigentes final actual = _colores[_colorIndex]; // Extrae la configuración cromática activa
return Scaffold( // Andamio general de la pantalla backgroundColor: actual['color'] as Color, // Aplica el color de fondo dinámico appBar: AppBar( // Barra superior de navegación title: const Text('Pantalla de Colores (StatefulWidget)'), // Título de la vista ), // Fin de AppBar body: Center( // Centra el contenido en pantalla child: Column( // Distribuye verticalmente los componentes mainAxisAlignment: MainAxisAlignment.center, // Alineación vertical centrada children: [ // Widgets hijos Text( // Muestra el nombre del color seleccionado 'Color actual: ${actual['nombre']}', // Interpolación de texto con el dato dinámico style: TextStyle( // Estilo tipográfico adaptado fontSize: 22, // Tamaño de fuente en píxeles lógicos fontWeight: FontWeight.bold, // Grosor negrita color: actual['textoColor'] as Color, // Color de texto de contraste ), // Fin de TextStyle ), // Fin de Text const SizedBox(height: 24), // Separación vertical de 24 píxeles ElevatedButton.icon( // Botón con icono descriptivo onPressed: _rotarColor, // Asocia el evento clic a la función mutadora icon: const Icon(Icons.palette), // Icono de paleta de pintura label: const Text('Cambiar Siguiente Color'), // Etiqueta del botón ), // Fin de ElevatedButton.icon ], // Fin de children ), // Fin de Column ), // Fin de Center ); // Fin de Scaffold } // Fin del método build} // Fin de la clase _PantallaColoresStatePuntos clave del funcionamiento
Sección titulada «Puntos clave del funcionamiento»createState(): Es el método delStatefulWidgetque crea la instancia del estado mutable asociado (_PantallaColoresState).setState(() { ... }): Es la llamada obligatoria para modificar variables de estado. Modifica_colorIndexe inmediatamente marca el widget como “sucio” (dirty), programando una ejecución debuild()en el siguiente fotograma del motor de renderizado.- Operador módulo
% _colores.length: Al sumar 1, cuando el índice alcanza el valor 4, el resto de la división4 % 4es 0, haciendo que la rotación sea un bucle infinito seguro sin riesgo de desbordar la lista.