Flutter Widgets — los componentes básicos de la interfaz de usuario en el framework Google Flutter, lanzado en la versión estable 1.0 en diciembre de 2018. En Flutter, todo es un widget: desde pantallas y botones hasta márgenes y alineación. Los widgets forman un árbol (widget tree) que Flutter renderiza en su propio motor Skia/Impeller, sin usar componentes nativos de la plataforma. Según Google I/O (2025), Flutter se utiliza en más de 500 000 aplicaciones en Google Play y App Store. La arquitectura de Flutter divide los widgets en StatelessWidget (inmutables) y StatefulWidget (con estado mutable mediante un objeto State).
Puntos Clave
Flutter Widgets — todos los elementos de UI en el framework Flutter, implementados como clases Dart inmutables. Un widget es la configuración de un elemento de UI: su tamaño, color, posición y manejadores de eventos. A diferencia de Android (XML + View) o iOS (Storyboard + UIView), Flutter no usa componentes nativos — todo se dibuja con el motor Skia (Android/iOS/Linux) o Impeller (iOS/macOS) en un Canvas. Esto garantiza una apariencia consistente en todas las plataformas sin diferencias de plataforma. Flutter incluye dos conjuntos de widgets: Material Widgets (Google Material Design 3 para Android/web) y Cupertino Widgets (Apple HIG para iOS/macOS). El desarrollador puede combinar ambos conjuntos en una misma aplicación. Cada widget tiene un método build() que devuelve un widget hijo o una composición de ellos — así se construye el árbol de widgets.
Flutter opera con tres árboles: Widget Tree (configuración, creado por el desarrollador), Element Tree (asignación del widget a su posición en el árbol, gestionado por el framework) y Render Tree (objetos que calculan el layout y realizan el pintado). Un Widget crea un Element, que crea un RenderObject. El Element se reutiliza cuando cambia la configuración (rebuild) — este es el mecanismo de optimización de Flutter: si el tipo de widget y la key coinciden, el Element no se recrea, sino que se actualiza con la nueva configuración. Comprender los tres árboles es clave para optimizar el rendimiento de las aplicaciones Flutter.
StatelessWidget — un widget que no almacena estado interno. Recibe parámetros a través del constructor y los muestra sin posibilidad de cambio después del build. StatelessWidget es ideal para elementos estáticos: encabezados, iconos, avatares, listas con datos fijos. El método build() se llama una vez al crearse y cuando cambia el widget padre. Como StatelessWidget no tiene estado, no requiere un objeto State separado — build() se define directamente en la clase del widget.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — un StatelessWidget que recibe name y avatarUrl a través del constructor. CircleAvatar muestra el avatar, Text muestra el nombre. El widget no puede cambiar estos valores después de crearse. Usar un constructor const (const ProfileHeader) permite a Flutter reutilizar la instancia del widget durante el rebuild del padre — una microoptimización recomendada para todos los StatelessWidget.
StatefulWidget — un widget con estado mutable almacenado en un objeto State separado. El StatefulWidget en sí es inmutable, como StatelessWidget. La parte mutable se delega a State: State es un objeto que se crea una vez y sobrevive a múltiples rebuilds del widget. Cuando el estado cambia (setState()), Flutter llama a build() en el State, actualizando la UI. StatefulWidget se usa para elementos interactivos: contadores, campos de texto, casillas de verificación, animaciones, temporizadores.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — un StatefulWidget con la clase State _LikeButtonState. Los campos liked y count son estado almacenado en State y no se reinician en el rebuild. setState() notifica a Flutter que la UI necesita reconstruirse. Flutter no recrea State en cada rebuild del padre — solo cuando cambia la configuración (key o tipo de widget). En IT Sectr, usamos StatelessWidget para la visualización y StatefulWidget para componentes interactivos, siguiendo el principio de minimizar StatefulWidget hasta los límites de la mutación.
Widget Tree — una estructura jerárquica de widgets que describe la UI de la aplicación. Flutter convierte el Widget Tree en un Element Tree: cada Widget crea un Element, que rastrea su posición en el árbol y su conexión con un RenderObject. El Render Tree realiza el layout (determinación de tamaños y posiciones) y el paint (renderizado). El Element es una capa de optimización clave: si el tipo de widget y la key no han cambiado durante un rebuild, el Element se reutiliza, actualizando la configuración sin recrear el RenderObject. Esto garantiza el rendimiento de Flutter a altas tasas de fotogramas (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Widgets de Flutter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'¡Hola, Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}Árbol de widgets de HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold es el widget raíz de layout de Material Design. Center centra su Column hijo. Column organiza los hijos verticalmente con alineación centrada (mainAxisAlignment.center). Flutter calcula el layout de arriba abajo (las constraints se pasan del padre) y los tamaños de abajo arriba (sizedByParent o sizing from children).
BuildContext — un descriptor de la posición del widget en el Element Tree. Cada método build() recibe un BuildContext, a través del cual el widget puede acceder a: MediaQuery (tamaño de pantalla, orientación, densidad de píxeles, safe area), Theme (MaterialThemeData o CupertinoThemeData), Navigator (pila de navegación), ScaffoldMessenger (SnackBar), InheritedWidget (paso de datos hacia abajo en el árbol). BuildContext no debe guardarse después de que build() termine ni usarse fuera de un contexto síncrono — esto provoca errores como “Scaffold.of() called with a context that does not contain a Scaffold”. En lugar de guardar el context, usa el widget Builder o el patrón InheritedWidget para acceder a los datos.
Key — un parámetro opcional del constructor de cada widget (super.key). Key ayuda a Flutter a identificar un widget cuando cambia el orden o la cantidad de elementos en una lista. Sin key, Flutter compara los widgets por tipo y posición; al añadir un elemento en medio de una lista sin key, Flutter reutiliza el Element para el widget incorrecto, causando errores de estado (StatefulWidget) y problemas de animación. Usa ValueKey (identificador único) para listas, ObjectKey (basado en el objeto de datos), UniqueKey (garantizado único en cada rebuild — para recreación forzada).
Flutter SDK (versión estable 3.3+, Dart 3+) incluye más de 200 widgets integrados divididos en categorías: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) y Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Los widgets de layout son la base de cualquier UI de Flutter: Row para secuencias horizontales, Column para verticales, Stack para elementos superpuestos, Container con BoxDecoration para decoración.
| Categoría | Widgets clave | Propósito |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Posicionamiento y dimensionamiento de hijos |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | Componentes UI de Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | Componentes con estilo iOS |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Efectos visuales y recorte |
| Async | FutureBuilder, StreamBuilder | Carga de datos asíncrona con estados de UI |
| Accessibility | Semantics, MergeSemantics | Marcado semántico para lectores de pantalla |
Preguntas Frecuentes
StatelessWidget no tiene estado interno — todos los datos se pasan a través del constructor y no cambian. StatefulWidget almacena el estado mutable en un objeto State separado que sobrevive a los rebuilds. El cambio de estado llama a setState(), y Flutter reconstruye la UI. Usa StatelessWidget para elementos inmutables; usa StatefulWidget para elementos interactivos.
BuildContext es un descriptor de la posición del widget en el Element Tree, pasado al método build(). A través del context, un widget accede a MediaQuery, Theme, Navigator, ScaffoldMessenger e InheritedWidget. BuildContext no debe guardarse después de que build() termine. Para acceder a datos, usa el widget Builder o InheritedWidget.
Sí, Flutter usa Dart como su único lenguaje de programación. Dart es un lenguaje de tipado estático con null safety, sound null safety, extension methods y pattern matching. Para empezar, basta con conocimientos básicos de Dart: clases, funciones, async/await, colecciones. Dart se compila a código nativo (AOT) mediante Dart Native y a JavaScript (para web) mediante Dart2JS.
No, Flutter soporta seis plataformas: iOS, Android, Web, macOS, Windows, Linux. Más del 90% del código es compartido entre todas las plataformas. Las adaptaciones de plataforma (cámara, sistema de archivos) se implementan mediante plugins o platform channels. Para escritorio, Flutter usa el shell de ventanas Flutter Desktop; para web, usa el motor CanvasKit (WebGL) o el renderizador HTML.
Flutter logra 60/120 FPS mediante: su propio motor 2D (Skia/Impeller), la ausencia de un bridge nativo (a diferencia de React Native), tres árboles (Widget → Element → Render) con reutilización de Element cuando el tipo/key no cambian, un algoritmo de layout con un solo paso (constraints hacia abajo, sizes hacia arriba) y RepaintBoundary para aislar el repintado de áreas individuales de la pantalla.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también